题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2330
差分约束裸题。练习用spfa判正环(一个点入队超过n次)。
据说有1e5个点连成一条链的数据,使得0点从1到n加边会TLE,而从n到1加边就300ms。为什么?
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int N=1e5+5; int n,m,head[N],xnt,dis[N],ct[N]; long long ans; bool in[N]; struct Edge{ int next,to,w; Edge(int n=0,int t=0,int w=0):next(n),to(t),w(w) {} }edge[N*3]; bool spfa() { queue<int> q; memset(dis,-1,sizeof dis); q.push(0);in[0]=1;dis[0]=0; while(q.size()) { int k=q.front();q.pop();in[k]=0; for(int i=head[k],v;i;i=edge[i].next) if(dis[k]+edge[i].w>dis[v=edge[i].to]) { if(++ct[v]>=n)return 1; dis[v]=dis[k]+edge[i].w; if(!in[v])q.push(v),in[v]=1; } } return 0; } int main() { scanf("%d%d",&n,&m);int k,x,y; for(int i=n;i;i--)// edge[++xnt]=Edge(head[0],i,1),head[0]=xnt; for(int i=1;i<=m;i++) { scanf("%d%d%d",&k,&x,&y); if(k==1) {edge[++xnt]=Edge(head[x],y,0);head[x]=xnt; edge[++xnt]=Edge(head[y],x,0);head[y]=xnt;} if(k==2){if(x==y){printf("-1");return 0;} edge[++xnt]=Edge(head[x],y,1),head[x]=xnt;} if(k==3)edge[++xnt]=Edge(head[y],x,0),head[y]=xnt; if(k==4){if(x==y){printf("-1");return 0;} edge[++xnt]=Edge(head[y],x,1),head[y]=xnt;} if(k==5)edge[++xnt]=Edge(head[x],y,0),head[x]=xnt; } if(spfa()) { printf("-1");return 0; } for(int i=1;i<=n;i++)ans+=dis[i]; printf("%lld",ans); return 0; }