题目大意:给定n个点和之间的大小关系,求每个点最少是多少(必须大于0)
差分约束系统,按照题目说的连边即可,记住少于和不少于的大小关系是不一样的
边集要开3倍 此外注意的是0到i的连边要从后往前连 不然TLE 坑B数据逗死我了
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 100100 using namespace std; struct abcd{ int to,f,next; }table[M*3]; int head[M],tot; int n,m; long long ans; int f[M],times[M]; bool v[M]; void SPFA() { int i; static queue<int> q; memset(f,0xef,sizeof f); q.push(0);f[0]=0; while( q.size() ) { int x=q.front();q.pop(); v[x]=0; for(i=head[x];i;i=table[i].next) if(f[table[i].to]<f[x]+table[i].f) { f[table[i].to]=f[x]+table[i].f; times[table[i].to]=times[x]+1; if(times[table[i].to]>n+1) { puts("-1"); exit(0); } if(!v[table[i].to]) v[table[i].to]=1,q.push(table[i].to); } } } void Add(int x,int y,int z) { table[++tot].to=y; table[tot].f=z; table[tot].next=head[x]; head[x]=tot; } int main() { int i,p,x,y; cin>>n>>m; for(i=1;i<=m;i++) { scanf("%d%d%d",&p,&x,&y); switch(p) { case 1: Add(x,y,0); Add(y,x,0); break; case 4: swap(x,y); case 2: Add(x,y,1); break; case 3: swap(x,y); case 5: Add(x,y,0); break; } } for(i=n;i;i--) Add(0,i,1); SPFA(); for(i=1;i<=n;i++) ans+=f[i]; cout<<ans<<endl; }
原文地址:http://blog.csdn.net/popoqqq/article/details/40742755