POJ--1364(差分约束)
2015-01-07 21:18:11
思路:差分约束水题?.....写了好久啊!(之前老不过...后来怒写了3个版本)
根据要求建图即可,跑最长路/最短路都行。由于图可能是不连通的,所以方法1:建立超级起点,与0~n所有点建立0权边。方法2:对有所点跑一遍最短路(可以初始把所有点放入队列。)
如果跑最短路:对于约束一:S(i + j) - S(i - 1) > C --> S(a - 1) <= S(a + b) - (C + 1)
对于约束二:S(i + j) - S(a - 1) < C --> S(i + j) <= S(a - 1) + (C - 1)
然后用bellman-ford / spfa 判负环都可。(spfa的dfs版应该更快)
(1)spfa(bfs)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <iostream> 11 #include <algorithm> 12 using namespace std; 13 #define lp (p << 1) 14 #define rp (p << 1|1) 15 #define getmid(l,r) (l + (r - l) / 2) 16 #define MP(a,b) make_pair(a,b) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 typedef pair<int,int> pii; 20 const int INF = (1 << 30) - 1; 21 const int maxn = 110; 22 23 int n,m; 24 int first[maxn],ecnt; 25 int cnt[maxn],inq[maxn],dis[maxn]; 26 27 struct edge{ 28 int v,next,cost; 29 }e[maxn << 1]; 30 31 bool Spfa(int s){ 32 queue<int> Q; 33 memset(inq,0,sizeof(inq)); 34 memset(cnt,0,sizeof(cnt)); 35 fill(dis,dis + n + 1,INF); 36 inq[s] = cnt[s] = 1; 37 dis[s] = 0; 38 Q.push(s); 39 while(!Q.empty()){ 40 int x = Q.front(); Q.pop(); 41 inq[x] = 0; 42 for(int i = first[x]; ~i; i = e[i].next){ 43 int v = e[i].v; 44 if(dis[v] > dis[x] + e[i].cost){ 45 dis[v] = dis[x] + e[i].cost; 46 if(inq[v] == 0){ 47 inq[v] = 1; 48 cnt[v]++; 49 if(cnt[v] > n + 1) //这里稍微写大点也没事 50 return false; 51 Q.push(v); 52 } 53 } 54 } 55 } 56 return true; 57 } 58 59 void Add_edge(int u,int v,int c){ 60 e[++ecnt].next = first[u]; 61 e[ecnt].v = v; 62 e[ecnt].cost = c; 63 first[u] = ecnt; 64 } 65 66 int main(){ 67 int a,b,c; 68 char s[10]; 69 while(scanf("%d",&n) != EOF,n){ 70 memset(first,-1,sizeof(first)); 71 ecnt = 0; 72 scanf("%d",&m); 73 for(int i = 1; i <= m; ++i){ 74 scanf("%d%d%s%d",&a,&b,s,&c); 75 if(s[0] == 'g') Add_edge(a + b,a - 1,-c - 1); 76 else Add_edge(a - 1,a + b,c - 1); 77 } 78 for(int i = 0; i <= n; ++i) Add_edge(n + 1,i,0); 79 if(Spfa(n + 1)) printf("lamentable kingdom\n"); 80 else printf("successful conspiracy\n"); 81 } 82 return 0; 83 }
(2)spfa(dfs,递归)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <iostream> 11 #include <algorithm> 12 using namespace std; 13 #define lp (p << 1) 14 #define rp (p << 1|1) 15 #define getmid(l,r) (l + (r - l) / 2) 16 #define MP(a,b) make_pair(a,b) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 typedef pair<int,int> pii; 20 const int INF = (1 << 30) - 1; 21 const int maxn = 110; 22 23 int n,m; 24 int first[maxn],ecnt; 25 int cnt[maxn],inq[maxn],dis[maxn]; 26 27 struct edge{ 28 int v,next,cost; 29 }e[maxn << 1]; 30 31 bool Spfa(int p){ 32 inq[p] = 1; //入栈 33 for(int i = first[p]; i != -1; i = e[i].next){ 34 int v = e[i].v; 35 if(dis[v] > dis[p] + e[i].cost){ 36 dis[v] = dis[p] + e[i].cost; 37 if(inq[v] == 0){ 38 inq[v] = 1; 39 if(Spfa(v) == false) return false; 40 } 41 else return false; 42 } 43 } 44 inq[p] = 0; //出栈 45 return true; 46 } 47 48 void Add_edge(int u,int v,int c){ 49 e[++ecnt].next = first[u]; 50 e[ecnt].v = v; 51 e[ecnt].cost = c; 52 first[u] = ecnt; 53 } 54 55 int main(){ 56 int a,b,c; 57 char s[10]; 58 while(scanf("%d",&n) != EOF,n){ 59 memset(first,-1,sizeof(first)); 60 ecnt = 0; 61 scanf("%d",&m); 62 for(int i = 1; i <= m; ++i){ 63 scanf("%d%d%s%d",&a,&b,s,&c); 64 if(s[0] == 'g') Add_edge(a + b,a - 1,-c - 1); 65 else Add_edge(a - 1,a + b,c - 1); 66 } 67 for(int i = 0; i <= n; ++i) Add_edge(n + 1,i,0); 68 memset(inq,0,sizeof(inq)); 69 fill(dis,dis + n + 1,INF); 70 dis[n + 1] = 0; 71 if(Spfa(n + 1)) printf("lamentable kingdom\n"); 72 else printf("successful conspiracy\n"); 73 } 74 return 0; 75 }
(3)bellman-ford
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <iostream> 11 #include <algorithm> 12 using namespace std; 13 #define lp (p << 1) 14 #define rp (p << 1|1) 15 #define getmid(l,r) (l + (r - l) / 2) 16 #define MP(a,b) make_pair(a,b) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 typedef pair<int,int> pii; 20 const int INF = (1 << 30) - 1; 21 const int maxn = 110; 22 23 int n,m; 24 int first[maxn],ecnt; 25 int cnt[maxn],inq[maxn],dis[maxn]; 26 27 struct edge{ 28 int u,v,next,cost; 29 }e[maxn << 1]; 30 31 bool BF(){ 32 fill(dis + 1,dis + n + 1,INF); 33 dis[0] = 0; 34 for(int i = 1; i <= n; ++i){ 35 for(int j = 1; j <= ecnt; ++j){ 36 int u = e[j].u; 37 int v = e[j].v; 38 int c = e[j].cost; 39 if(dis[v] > dis[u] + c){ 40 dis[v] = dis[u] + c; 41 } 42 } 43 } 44 for(int i = 1; i <= ecnt; ++i){ 45 int u = e[i].u; 46 int v = e[i].v; 47 int c = e[i].cost; 48 if(dis[v] > dis[u] + c) return false; 49 } 50 return true; 51 } 52 53 void Add_edge(int u,int v,int c){ 54 e[++ecnt].next = first[u]; 55 e[ecnt].u = u; 56 e[ecnt].v = v; 57 e[ecnt].cost = c; 58 first[u] = ecnt; 59 } 60 61 int main(){ 62 int a,b,c; 63 char s[10]; 64 while(scanf("%d",&n) != EOF,n){ 65 memset(first,-1,sizeof(first)); 66 ecnt = 0; 67 scanf("%d",&m); 68 for(int i = 1; i <= m; ++i){ 69 scanf("%d%d%s%d",&a,&b,s,&c); 70 if(s[0] == 'g'){ 71 Add_edge(a + b,a - 1,-(c + 1)); 72 } 73 else{ 74 Add_edge(a - 1,a + b,c - 1); 75 } 76 } 77 if(BF()) printf("lamentable kingdom\n"); 78 else printf("successful conspiracy\n"); 79 } 80 return 0; 81 }