bzoj2330(差分约束)

题解:这道题是练差分约束的一道好题目吧,我具体在代码中注释,这样更加好理解,

为什么求最长路呢?因为这样保证了满足条件,如果存在正权环,就表示无解,就是

正权环之间不断要更多的糖果才行。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<queue>
 7 using namespace std;
 8 
 9 typedef long long ll;
10 const int N=100007;
11 
12 int s,dis[N],mark[N],n,m;
13 int cnt=0,head[N],next[N*3],rea[N*3],val[N*3];
14 bool vis[N];
15 
16 void add(int u,int v,int fee)
17 {
18     cnt++;
19     next[cnt]=head[u];
20     head[u]=cnt;
21     rea[cnt]=v;
22     val[cnt]=fee;
23 }
24 bool spfa()
25 {
26     queue<int>q;
27     q.push(0);
28     vis[dis[0]=0]=1;
29     while(!q.empty())
30     {
31         int u=q.front();q.pop();
32         for(int i=head[u];i!=-1;i=next[i])
33         {
34             int v=rea[i],fee=val[i];
35             if(dis[u]+fee>dis[v])
36             {
37                 dis[v]=dis[u]+fee;
38                 if(++mark[v]>=n) return 0;//表示无法满足 
39                 if(!vis[v])
40                 {
41                     vis[v]=1;
42                     q.push(v);
43                 }
44             }
45         }
46         vis[u]=0;
47     }
48     return 1;
49 }
50 int main()
51 {
52     memset(head,-1,sizeof(head));
53     scanf("%d%d",&n,&m);
54     for (int i=1;i<=m;i++)
55     {
56         int xh,u,v;
57         scanf("%d%d%d",&xh,&u,&v);
58         switch (xh)
59         {
60             case 1:if(u!=v) add(u,v,0),add(v,u,0);
61                 break;
62             case 2:if(u==v)
63                 {
64                     printf("-1");
65                     return 0;
66                 }
67                 add(u,v,1);break;                    
68             case 3:if(u!=v) add(v,u,0);break;//表示可以到达 
69             case 4:if(u==v)
70                 {
71                     printf("-1");
72                     return 0;
73                 }
74                 add(v,u,1);break;//因为最少,所以只要多一格糖果就可以了。 
75             case 5:if(u!=v) add(u,v,0);break;
76         }
77     }
78     for(int i=n;i;i--)
79         add(0,i,1);//初始,开辟超源点。 
80     if(!spfa()) printf("-1");
81     else
82     {
83         ll ans=0;
84         for(int i=1;i<=n;i++) 
85             ans+=dis[i];
86         printf("%lld\n",ans);
87     }
88 }

 

posted @ 2017-08-25 21:06  Kaiser-  阅读(307)  评论(0编辑  收藏  举报