[BZOJ2330][SCOI2011]糖果 差分约束系统+最短路

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2330

类似于题目中这种含有不等式关系,我们可以建立差分约束系统来跑最长路或最短路。

对于一个不等式$X_1-X_2>=a$我们可以看成是$X_1>=X_2+a$,把$X_1$和$X_2$看成两个点,我们可以发现这个关系跟最长路中的$dis[v]>=dis[u]+w[i]$很像,就是最长路中的点一定满足这样的关系。

所以我们就按着这个思路,先把关于点$X_1$,$X_2$和边$a$的图建好,再来跑一遍最长路,如果有解,就一定满足题目中的不等式关系。

具体连边方式就是若有$a>=b+c$,则连$b$到$a$,边权为$c$。最短路同理。

最长路无解的情况就是存在正权环,最短路存在负权环。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 typedef long long ll;
 7 const int INF=1<<30;
 8 int inline readint(){
 9     int Num;char ch;
10     while((ch=getchar())<'0'||ch>'9');Num=ch-'0';
11     while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0';
12     return Num;
13 }
14 int N,K;
15 int to[300010],ne[300010],w[300010],fir[100010],cnt=0;
16 void Add(int a,int b,int c){
17     to[++cnt]=b;
18     w[cnt]=c;
19     ne[cnt]=fir[a];
20     fir[a]=cnt;
21 }
22 int vis[100010],dis[100010];
23 bool in[100010];
24 queue <int> q;
25 ll spfa(){
26     for(int i=1;i<=N;i++) dis[i]=-INF;
27     in[N+1]=true;
28     q.push(N+1);
29     dis[N+1]=0;
30     vis[N+1]=1;
31     int u;
32     while(!q.empty()){
33         u=q.front();
34         q.pop();
35         in[u]=false;
36         for(int i=fir[u];i!=-1;i=ne[i]){
37             int v=to[i];
38             if(dis[v]<dis[u]+w[i]){
39                 dis[v]=dis[u]+w[i];
40                 if(!in[v]){
41                     q.push(v);
42                     in[v]=true;
43                     vis[v]++;
44                     if(vis[v]>N) return -1;
45                 }
46             }
47         }
48     }
49     ll ans=0;
50     for(int i=1;i<=N;i++) ans+=dis[i];
51     return ans; 
52 }
53 int main(){
54     memset(fir,-1,sizeof(fir));
55     N=readint();
56     K=readint();
57     for(int i=1;i<=K;i++){
58         int X=readint(),
59             A=readint(),
60             B=readint();
61         switch(X){
62             case 1:
63                 Add(B,A,0);
64                 Add(A,B,0);
65                 break;
66             case 2:
67                 if(A==B){
68                     puts("-1");
69                     return 0;
70                 }
71                 Add(A,B,1);
72                 break;
73             case 3:
74                 Add(B,A,0);
75                 break;
76             case 4:
77                 if(A==B){
78                     puts("-1");
79                     return 0;
80                 }
81                 Add(B,A,1);
82                 break;
83             case 5:
84                 Add(A,B,0);
85                 break;
86         }
87     }
88     for(int i=N;i>=1;i--) Add(N+1,i,1);
89     printf("%lld\n",spfa());
90     return 0;
91 }

 

posted @ 2017-10-03 18:52  halfrot  阅读(162)  评论(0编辑  收藏  举报