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)

 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 }
View Code

(2)spfa(dfs,递归)

 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 }
View Code

(3)bellman-ford

 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 }
View Code

 

转载于:https://www.cnblogs.com/naturepengchen/articles/4209496.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值