【差分约束系统/DFS版SPFA】BZOJ3436-小K的农场
【题目大意】
总共n个农场,有以下三种描述:农场a比农场b至少多种植了c个单位的作物,农场a比农场b至多多种植了c个单位的作物,农场a与农场b种植的作物数一样多。问是否有可能性。
【思路】
农场a比农场b至少多种植了c个单位的作物:a>=b+c → b<=a-c,由a向b连一条-c的边。
农场a比农场b至多多种植了c个单位的作物:a<=b+c,由b向a连一条c的边。
农场a与农场b种植的作物数一样多:a=b → b<=a<=b,互相连一条0的边。
SPFA判断负环,要用DFS版本的来。DFS版本的直接参考了rausen学长的……真是快到飞起(;′⌒`)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXN=10000+50; 4 struct edge 5 { 6 int to,len; 7 }; 8 int n,m; 9 vector<edge> E[MAXN]; 10 int vis[MAXN],dis[MAXN],flag; 11 12 void addedge(int u,int v,int w) 13 { 14 E[u].push_back((edge){v,w}); 15 } 16 17 void init() 18 { 19 scanf("%d%d",&n,&m); 20 for (int i=1;i<=m;i++) 21 { 22 int op,a,b,c; 23 scanf("%d",&op); 24 if (op==1)//a-b>=c 25 { 26 scanf("%d%d%d",&a,&b,&c); 27 addedge(a,b,-c); 28 } 29 if (op==2) 30 { 31 scanf("%d%d%d",&a,&b,&c); 32 addedge(b,a,c); 33 } 34 if (op==3) 35 { 36 scanf("%d%d",&a,&b); 37 addedge(a,b,0);addedge(b,a,0); 38 } 39 } 40 } 41 42 void spfa(int fr) 43 { 44 if (vis[fr]) 45 { 46 flag=1; 47 return; 48 } 49 vis[fr]=1; 50 for (int i=0;i<E[fr].size();i++) 51 { 52 int to=E[fr][i].to,len=E[fr][i].len; 53 if (dis[fr]+len<dis[to]) 54 { 55 dis[to]=dis[fr]+len; 56 spfa(to); 57 if (flag) return; 58 } 59 } 60 vis[fr]=0; 61 } 62 63 void solve() 64 { 65 memset(vis,0,sizeof(vis)); 66 for (int i=1;i<=n;i++) 67 { 68 spfa(i); 69 if (flag) break; 70 } 71 puts(flag?"No":"Yes"); 72 } 73 74 int main() 75 { 76 init(); 77 solve(); 78 return 0; 79 }