判断是否存在负环

1行:一个整数F表示接下来会有F个农场说明。

每个农场第一行:分别是三个空格隔开的整数:NMW

2行到M+1行:三个空格分开的数字(SET)描述,分别为:需要T秒走过SE之间的双向路径。两个区域可能由一个以上的路径来连接。

M +2M+ W+1行:三个空格分开的数字(SET)描述虫洞,描述单向路径,SE且回溯T秒。

 

2

3 3 1

1 2 2

1 3 4

2 3 1

3 1 3

3 2 1

1 2 3

2 3 4

3 1 8

输出

F行,每行代表一个农场

每个农场单独的一行,” YES”表示能满足要求,”NO”表示不能满足要求。

NO

YES

思路很简单,只要判断是否存在负权环就行了,用floyd一次搞定!(小心min函数,我因为加了min函数而超时了),详情见注释

int map[505][505],n,m,k,num=0;  

int floyd()  

{  

    int i,j,k,f=0;  

    for(k=1;k<=n;k++)  

        for(i=1;i<=n;i++){  

            for(j=1;j<=n;j++)  

            {  

                int t=map[i][k]+map[k][j];  

                if(map[i][j]>t)map[i][j]=t;  

                /*map[i][j]=min(map[i][j],map[i][k]+map[k][j]);*/  

            }  

            if(map[i][i]<0)return 1;  

    }  

    return f;  

}  

int main()  

{  

    int t;  

    scanf("%d",&t);  

    while(t--)  

    {  

        int i,j,a,b,c;  

        scanf("%d%d%d",&n,&m,&k);  

        memset(map,0x3f3f3f3f,sizeof(map));  

        for(i=1;i<=n;i++)map[i][i]=0;  

        for(i=1;i<=m;i++)  

        {  

            scanf("%d%d%d",&a,&b,&c);  

            if(c<map[a][b])map[a][b]=map[b][a]=c;  

        }  

        for(i=1;i<=k;i++)  

        {  

            scanf("%d%d%d",&a,&b,&c);  

            map[a][b]=-c;  

        }  

        num++;  

        int f=floyd();  

        if(!f)printf("NO\n");  

        else printf("YES\n");  

    }  

    return 0;  

}

Bellman 算法

思路:根据BELLMAN-FORD算法,如果图中不存在从s可达的负圈,那么最短路不过经过同一个顶点两次,也就是说最多经过V-1条边,

如果存在负圈,那么这个循环更新次数会在第n次也会更新,实际上会无限更新,越来越小,所以一开始对所以点i,都把d[i]初始化为0,那么可以检查

出所有的负圈:

const int MAXN=5500;  

struct edge{  

    int from,to,cost;  

}ed[MAXN];  

int n,m,w;  

bool solve(int e)  

{  

    int dis[510];  

    for(int i=0;i<510;i++) dis[i]=0;  

  

    for(int i=0;i<n;i++){  

        for(int j=0;j<e;j++){  

            edge es=ed[j];  

            if(dis[es.to]>dis[es.from]+es.cost){  

                dis[es.to]=dis[es.from]+es.cost;  

                  

                if(i==n-1) return 1; // 如果第n-1次还更新,那么存在负圈   

            }  

        }  

    }  

    return 0;  

}  

int main()  

{  

    int T;  

    cin>>T;  

    while(T--)  

    {  

          

        cin>>n>>m>>w;  

        int cnt=0;  

        for(int i=0;i<m;i++){  

            int x,y,z;  

            cin>>x>>y>>z;  

            ed[cnt].from=x;  

            ed[cnt].to=y;  

            ed[cnt++].cost=z;  

            ed[cnt].from=y;  

            ed[cnt].to=x;  

            ed[cnt++].cost=z;  

        }  

        for(int i=0;i<w;i++){  

            int x,y,z;  

            cin>>x>>y>>z;  

            ed[cnt].from=x;  

            ed[cnt].to=y;  

            ed[cnt++].cost=-z;  

        }  

        if(solve(cnt)) cout<<"YES"<<endl;  

        else cout<<"NO"<<endl;  

    }  

    return 0;  

}  

 

 

 

猜你喜欢

转载自blog.csdn.net/yihanyifan/article/details/80182733