#差分约束,正环,最长路,SPFA#洛谷 3275 JZOJ 2406 糖果

题目链接


分析

按照题目的要求跑最长路,注意源点要倒序加边,不然会T掉一个点


代码

#include 
#include 
#include 
#include 
#define rr register
using namespace std;
struct node{int y,w,next;}e[300001];
int dis[100011],ls[100011],cnt[100011],n,k=1; bool v[100011];
inline signed iut(){
    rr int ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    return ans;
}
inline void add(int x,int y,int w){
    e[++k]=(node){y,w,ls[x]},ls[x]=k;
}
signed main(){
    n=iut();
    for (rr int m=iut();m;--m){
        rr int q=iut(),x=iut(),y=iut();
        if (q==1) add(x,y,0),add(y,x,0);
        else if (q==2){
            if (x==y) return !printf("-1");
            add(x,y,1);
        }
        else if (q==3) add(y,x,0);
        else if (q==4){
            if (x==y) return !printf("-1");
            add(y,x,1);
        }else add(x,y,0);
    }
    for (rr int i=n;i;--i) add(n+1,i,1);//表示至少有一个糖果
    rr queue<int>q; q.push(n+1);
    while (q.size()){
        rr int x=q.front(); q.pop();
        if ((++cnt[x])==n) return !printf("-1");//出现正环
        for (rr int i=ls[x];i;i=e[i].next)
        if (dis[e[i].y]<dis[x]+e[i].w){
            dis[e[i].y]=dis[x]+e[i].w;
            if (!v[e[i].y]) q.push(e[i].y);
        }
        v[x]=0;
    }
    rr long long ans=0;
    for (rr int i=1;i<=n;++i) ans+=dis[i];
    return !printf("%lld",ans);
}

你可能感兴趣的:(最短路径,负环与差分约束系统)