题解:这道题是练差分约束的一道好题目吧,我具体在代码中注释,这样更加好理解,
为什么求最长路呢?因为这样保证了满足条件,如果存在正权环,就表示无解,就是
正权环之间不断要更多的糖果才行。
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 }