AcWing368 银河(差分约束)
本题数据量比较大,可以用tarjan缩点后判环,我使用的是差分约束,如果存在环的情况,最好将队列换成栈。
但是在普通求spfa的时候,还是要用队列。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; const int N=3e5+10; int h[N],ne[N],e[N],w[N],idx; void add(int a,int b,int c){ e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++; } int n,m; int st[N],dis[N]; int cnt[N]; bool spfa(){ memset(dis,-0x3f,sizeof dis); stack<int> q; q.push(0); dis[0]=0; st[0]=1; int count=0; while(q.size()){ int t=q.top(); q.pop(); st[t]=0; int i; for(i=h[t];i!=-1;i=ne[i]){ int j=e[i]; if(dis[j]<dis[t]+w[i]){ dis[j]=dis[t]+w[i]; cnt[j]=cnt[t]+1; if(cnt[j]>=n+1) return 0; if(!st[j]){ q.push(j); st[j]=1; } } } } return true; } int main(){ cin>>n>>m; memset(h,-1,sizeof h); int i; for(i=1;i<=m;i++){ int t,a,b; scanf("%d%d%d",&t,&a,&b); if(t==1){ add(a,b,0); add(b,a,0); } else if(t==2){ add(a,b,1); } else if(t==3){ add(b,a,0); } else if(t==4){ add(b,a,1); } else{ add(a,b,0); } } for(i=1;i<=n;i++){ add(0,i,1); } if(!spfa()){ cout<<-1<<endl; } else{ long long ans=0; for(i=1;i<=n;i++){ ans+=dis[i]; } cout<<ans<<endl; } }
没有人不辛苦,只有人不喊疼