【BZOJ - 3436】小K的农场(差分约束)
題干:
背景
小K是個特么喜歡玩MC的孩紙。。。
描述
小K在MC里面建立很多很多的農場,總共n個,以至于他自己都忘記了每個農場中種植作物的具體數量了,他只記得
一些含糊的信息(共m個),以下列三種形式描述:農場a比農場b至少多種植了c個單位的作物,農場a比農場b至多
多種植了c個單位的作物,農場a與農場b種植的作物數一樣多。但是,由于小K的記憶有些偏差,所以他想要知道存
不存在一種情況,使得農場的種植作物數量與他記憶中的所有信息吻合。
Input
第一行包括兩個整數n和m,分別表示農場數目和小K記憶中的信息的數目接下來m行:如果每行的第一個數是1,接
下來有三個整數a,b,c,表示農場a比農場b至少多種植了c個單位的作物如果每行第一個數是2,接下來有三個整數a
,b,c,表示農場a比農場b至多多種植了c個單位的作物如果每行第一個數是3,接下來有兩個整數a,b,表示農場a
種植的數量與b一樣。1<=n,m,a,b,c<=10000
Output
如果存在某種情況與小K的記憶吻合,輸出”Yes”,否則輸出”No”
Sample Input
3 3 3 1 2 1 1 3 1 2 2 3 2
Sample Output
Yes 樣例解釋 三個農場種植的數量可以為(2,2,1)
題目大意:
? 中文題意。
解題報告:
? 就是個差分約束的板子題,建完圖之后就看有沒有負環就可以。但是這題不保證點是連通的,所以你如果要直接跑負環的話需要以每一個點為起點開始跑,顯然是不合算的,所以最好的方式就是新建一個點,讓他到每一個點的連一條權值為0的邊,這樣就聯系起來了。
理性的解釋一下也解釋得通,因為你要加上一個點使得對原約束沒有任何影響(即不放大原有條件也不縮小原有條件(也就是添加新的約束)),就相當于0號點的值本該是-INF,所以加上了:對任意一個點V,,這樣一個限制,X0的取值是-INF,保證合法。
當然為了合法你加邊的時候權值是INF也行(當然得用longlong了不然就溢出了),代表的含義是
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<stack> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 2e5 + 5; const int INF = 0x3f3f3f3f; struct Edge {int ne,v,w; } e[MAX]; int tot,n,m; int head[MAX]; void add(int u,int v,int w) {e[++tot].v = v;e[tot].w = w;e[tot].ne = head[u];head[u] = tot; } int dis[MAX],cnt[MAX],vis[MAX]; bool spfa(int st) {memset(dis,INF,sizeof dis);queue<int> q;dis[st]=0;q.push(st);vis[st]=1; // cnt[st]=1;while(q.size()) {int cur = q.front(); q.pop();vis[cur]=0;for(int i = head[cur]; ~i; i = e[i].ne) {int v = e[i].v;if(dis[v] <= dis[cur] + e[i].w) continue;dis[v] = dis[cur] + e[i].w;if(!vis[v]) {cnt[v]=cnt[v]+1;vis[v]=1;q.push(v);if(cnt[v] > n) return 0;}}}return 1; } int main() {memset(head,-1,sizeof head);cin>>n>>m;for(int op,a,b,c,i = 1; i<=m; i++) {scanf("%d%d%d",&op,&a,&b);if(op != 3) scanf("%d",&c);if(op == 1) add(a,b,-c);if(op == 2) add(b,a,c);if(op == 3) {add(a,b,0);add(b,a,0);}}for(int i = 1; i<=n; i++) add(0,i,0);if(spfa(0)) puts("Yes");else puts("No");return 0 ; }?
總結
以上是生活随笔為你收集整理的【BZOJ - 3436】小K的农场(差分约束)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 科技板块有泡沫吗?科技股还能买吗?
- 下一篇: 【牛客 - 318L】彪神666(水题,