zoukankan      html  css  js  c++  java
  • poj3259Wormholes (Bellman_Ford/SPFA/Floyed算法判断是否存在负环)

    题目链接http://poj.org/problem?id=3259

    题目大意:一个图,有n个顶点,其中有m条边是双向的且权值为为正,w条边是单向的且权值为负,判断途中是否存在负环,如果有输出YES,没有输出NO。

    Sample Input

    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

    Sample Output

    NO
    YES


    解题思路:套用Bellman_Ford算法判断图是否存在负环
    具体详见代码:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int inf=0x3f3f3f3f;
    int n,m,w,dist[1000],tot;
    struct node{
        int from,to,d;
    }edge[3000];
    bool Bellman_Ford()
    {
        for(int i=1;i<=n;i++) dist[i]=inf;  //初始化 
        dist[1]=0;
        for(int i=1;i<n;i++)
        {
            bool flag=1;  //判断该轮是否可以松弛 
            for(int j=0;j<tot;j++)
            {
                if(dist[edge[j].to]>dist[edge[j].from]+edge[j].d)
                {  //进行松弛操作 
                    dist[edge[j].to]=dist[edge[j].from]+edge[j].d;
                    flag=0;
                }
            }
            if(flag) return false;  //当轮没有松弛表示没有负环 
        }
        for(int i=0;i<tot;i++)
        {
            if(dist[edge[i].to]>dist[edge[i].from]+edge[i].d)  //仍然可以松弛,表示有负环 
            return true;
        }
        return false;
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d",&n,&m,&w);
            tot=0;
            for(int i=1;i<=m;i++) //双向边 
            {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                edge[tot].from=a;
                edge[tot].to=b;
                edge[tot].d=c;
                tot++;
                edge[tot].from=b;
                edge[tot].to=a;
                edge[tot].d=c;
                tot++;
            }
            for(int i=1;i<=w;i++)  //单向负边 
            {
                scanf("%d%d%d",&edge[tot].from,&edge[tot].to,&edge[tot].d);
                edge[tot].d=-edge[tot].d;
                tot++;
            }
            if(Bellman_Ford())
                printf("YES
    ");
            else
                printf("NO
    ");
        }
        return 0;
    }

    套用SPFA算法判断图是否存在负环

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<string>
    #include<set>
    #include<cmath>
    #include<list>
    #include<deque>
    #include<cstdlib>
    #include<bitset>
    #include<stack>
    #include<map>
    #include<queue>
    using namespace std;
    typedef long long ll;
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    #define pushup() tree[rt]=tree[rt<<1]+tree[rt<<1|1]
    const int INF=0x3f3f3f3f;
    const double PI=acos(-1.0);
    const double eps=1e-6;
    const ll mod=1e9+7;
    const int maxn=100005;
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    const int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
    ll n,m,p;
    int head[maxn],vis[maxn],InQueue[maxn],dis[maxn];
    int tot;
    struct Edge{
        int to,w,next;
    }edge[maxn*2];
    void Add_Edge(int u,int v,int w)
    {
        edge[tot].to=v;
        edge[tot].w=w;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    bool spfa()
    {
        queue<int> que;
        while(que.size())que.pop();
        que.push(1);
        vis[1]=1;
        InQueue[1]++;
        dis[1]=0;
        while(que.size())
        {
            int u=que.front();
            que.pop();
            vis[u]=0;
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].to;
                if(dis[v]>dis[u]+edge[i].w)
                {
                    dis[v]=dis[u]+edge[i].w;
                    if(!vis[v])
                    {
                        vis[v]=1;
                        InQueue[v]++;
                        if(InQueue[v]>=n)return true;
                        que.push(v);
                    }
                }
            }
        }
        return false;
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            tot=0;
            cin>>n>>m>>p;
            for(int i=0;i<=n;i++)
            {
                vis[i]=InQueue[i]=0;
                dis[i]=INF;
                head[i]=-1;
            }
            int u,v,w;
            for(int i=0;i<m;i++)
            {
                cin>>u>>v>>w;
                Add_Edge(u,v,w);
                Add_Edge(v,u,w);
            }
            for(int i=0;i<p;i++)
            {
                cin>>u>>v>>w;
                w=-w;
                Add_Edge(u,v,w);
            }
            if(spfa()) puts("YES");
            else puts("NO");
        }
        return 0;
    }

    Floyed算法判断负环:

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<string>
    #include<set>
    #include<cmath>
    #include<list>
    #include<deque>
    #include<cstdlib>
    #include<bitset>
    #include<stack>
    #include<map>
    #include<queue>
    using namespace std;
    typedef long long ll;
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    #define pushup() tree[rt]=tree[rt<<1]+tree[rt<<1|1]
    const int INF=0x3f3f3f3f;
    const double PI=acos(-1.0);
    const double eps=1e-6;
    const ll mod=1e9+7;
    const int maxn=100005;
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    const int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
    int n,m,p,mp[505][505];
    bool Floyed()
    {
        for(int k=1;k<=n;k++)
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    if(mp[i][j]>mp[i][k]+mp[k][j])
                        mp[i][j]=mp[i][k]+mp[k][j];
                }
                if(mp[i][i]<0)return true;
            }
        }
        return false;
    }
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            cin>>n>>m>>p;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                {
                    if(i==j)mp[i][j]=0;
                    else mp[i][j]=INF;
                }
            int u,v,w;
            for(int i=0;i<m;i++)
            {
                cin>>u>>v>>w;
                if(w<mp[u][v]) mp[u][v]=mp[v][u]=w;
            }
            for(int i=0;i<p;i++)
            {
                cin>>u>>v>>w;
                mp[u][v]=-w;
            }
            if(Floyed())puts("YES");
            else puts("NO");
        }
        return 0;
    }
  • 相关阅读:
    Python作业之分页显示内容
    Codeforces Round #368 (Div. 2)
    数论专项测试——约数个数和(lucas的数论)
    数论专题测试——逆元
    数论专题测试——幸运数字
    bzoj2219: 数论之神
    bzoj3283: 运算器
    梅森素数
    后缀数组
    Hash_1014: [JSOI2008]火星人prefix
  • 原文地址:https://www.cnblogs.com/zjl192628928/p/9599502.html
Copyright © 2011-2022 走看看