这题是判断图中是否存在环(用最短路或最长路), 开始用spfa, 狂WA,想不通,看了讨论说要添加一个超源点,添加了就AC了。
总结:
用spfa算法判断图中是否存在环,要保证从源点开始,能到达各个顶点,这样才能保证差分约束里的各个不等式成立。因为要是源点到达不了某个顶点的话(即图是不连通的),那么从该顶点就无法入队,导致从该顶点出发的所有不等式,都没有得到检查。
---------------------------------------------------------------------------------------------------
/*差分约束系统第一个题目所谓 P A B X 可以转换为xa-xb<=1 xb-xa<=-1 注意要加两条边,因为是相等,所以要两个不等式把它卡死V A B 转化为 xb-xa<=-1Bellman_Ford弄一下就行了据说spfa也行.判断一个点入队列的次数.如果大于n的话,就说明有权值和为负的回路*/
---------------------------------------------------------------------------------------------------
CODE:
/*差分约束(判断是否存在环)*/ /*AC代码:469ms*/ #include <iostream> #define MAXN 1005 #define INF 0x7fffffff using namespace std; struct edge { int v,w,next; }E[20005]; int head[MAXN],ecnt; int Stack[MAXN],cnt[MAXN],dis[MAXN]; bool Instack[MAXN]; int N,M,top; //d[u]>=d[v]+w(v,u);最长路 void Insert(int u,int v,int w) { E[ecnt].v=v; E[ecnt].w=w; E[ecnt].next=head[u]; head[u]=ecnt++; } void Init() { int i,u,v,w; char s[2]; memset(head,-1,sizeof(head));ecnt=0; for(i=1;i<=M;i++) { scanf("%s",s); if(s[0]=='P') { scanf("%d%d%d",&u,&v,&w); Insert(v,u,w); Insert(u,v,-w);//d[v]>=d[u]-w(u,v); } else { scanf("%d%d",&u,&v); Insert(v,u,1);//d[u]>=d[v]+w(v,u) } } for(i=1;i<=N;i++)//保证连通性 Insert(0,i,0); } bool SPFA() { int i,u,v,w; memset(cnt,0,sizeof(cnt)); memset(Instack,false,sizeof(Instack)); for(i=1;i<=N;i++) dis[i]=-INF; top=0; Stack[top++]=0; Instack[0]=true; cnt[0]=1; dis[0]=0; while(top) { u=Stack[--top]; Instack[u]=false; cnt[u]++; if(cnt[u]>N) return false; for(i=head[u];i!=-1;i=E[i].next) { v=E[i].v;w=E[i].w; if(dis[v]<dis[u]+w) { dis[v]=dis[u]+w; if(!Instack[v]) { Stack[top++]=v; Instack[v]=true; } } } } return true; } int main() { while(scanf("%d%d",&N,&M)!=EOF) { Init(); if(SPFA()) printf("Reliable\n"); else printf("Unreliable\n"); } return 0; }