zoukankan      html  css  js  c++  java
  • P2850 [USACO06DEC]Wormholes G(负环判定)

    题目描述

    John 在他的农场中闲逛时发现了许多虫洞。虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前)。

    John 的每个农场有 mmm 条小路(无向边)连接着 nnn 块地(从 1∼n1 sim n1n 标号),并有 www 个虫洞。

    现在 John 想借助这些虫洞来回到过去(出发时刻之前),请你告诉他能办到吗。

    输入格式

    输入的第一行是一个整数 TTT,代表测试数据的组数。

    每组测试数据的格式如下:

    每组数据的第一行是三个用空格隔开的整数,分别代表农田的个数 nnn,小路的条数 mmm,以及虫洞的个数 www。

    每组数据的第 222 到第 (m+1)(m + 1)(m+1) 行,每行有三个用空格隔开的整数 u,v,pu, v, pu,v,p,代表有一条连接 uuu 与 vvv 的小路,经过这条路需要花费 ppp 的时间。

    每组数据的第 (m+2)(m + 2)(m+2) 到第 (m+w+1)(m + w + 1)(m+w+1) 行,每行三个用空格隔开的整数 u,v,pu, v, pu,v,p,代表点 uuu 存在一个虫洞,经过这个虫洞会到达点 vvv,并回到 ppp 秒之前。

    输出格式

    对于每组测试数据,输出一行一个字符串,如果能回到出发时刻之前,则输出 YES,否则输出 NO

    输入输出样例

    输入 #1
    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
    输出 #1
    NO
    YES

    显然,只要存在负环就一定能回到过去,不存在的话是不可能的。
    注意,这个题是给出一个图后往上添加负权边,不存在两个点之间只有一条负边的情况。
    然后这个题没有起点终点,但其实无所谓。
    注意开数组大小时,M必须要大于2500*2*500!!WA了半天TAT
    #include <bits/stdc++.h>
    #define N 505
    #define M 3005
    using namespace std;
    int n,m,w,tot=0;
    int head[N],edge[2*M],ver[2*M],Next[2*M],cnt[N],d[N];
    bool v[N];
    void add(int x,int y,int z)
    {
        ver[++tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot;
    }
    bool spfa()
    {
        queue<int>q;
        d[1]=0,v[1]=1,cnt[1]=0;
        q.push(1);
        while(q.size())
        {
            int x=q.front();
            q.pop();
            v[x]=0;
            int i;
            for(i=head[x];i;i=Next[i])
            {
                int y=ver[i],z=edge[i];
                if(d[y]>d[x]+z)
                {
                    d[y]=d[x]+z;
                    cnt[y]++;
                    if(cnt[y]>=n)return 1;
                    if(!v[y])q.push(y),v[y]=1;
                }
            }
        }
        while(q.size())q.pop();
        return 0;
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            memset(head,0,sizeof(head));
            memset(edge,0,sizeof(edge));
            memset(ver,0,sizeof(ver));
            memset(Next,0,sizeof(Next));
            memset(cnt,0,sizeof(cnt));
            memset(v,0,sizeof(v));
            memset(d,0x3f,sizeof(d));
            tot=0;
            cin>>n>>m>>w;
            int i,u,v,time;
            for(i=1;i<=m;i++)
            {
                scanf("%d%d%d",&u,&v,&time);
                add(u,v,time);
                add(v,u,time);
            }
            for(i=1;i<=w;i++)
            {
                scanf("%d%d%d",&u,&v,&time);
                add(u,v,-time);//手动转换为负数 
            }
            if(spfa())cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
        return 0;
    }


  • 相关阅读:
    mysql
    Hexo多台电脑同步
    Kaggle入门(一)——Digit Recognizer
    【视频编解码·学习笔记】13. 提取PPS信息程序
    【视频编解码·学习笔记】12. 图像参数集(PPS)介绍
    【视频编解码·学习笔记】11. 提取SPS信息程序
    【视频编解码·学习笔记】10. 序列参数集(SPS)介绍
    【视频编解码·学习笔记】9. 熵编码算法:指数哥伦布编解码程序
    【视频编解码·学习笔记】8. 熵编码算法:基本算法列举 & 指数哥伦布编码
    【视频编解码·学习笔记】7. 熵编码算法:基础知识 & 哈夫曼编码
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/12748100.html
Copyright © 2011-2022 走看看