• 洛谷 P2850 [USACO06DEC]虫洞Wormholes 判负环


    虫洞(wormhole)

    FJ 在农场上闲逛时,发现他的农场里有很多虫洞。虫洞是一条特殊的有向路径,当

    FJ 从它的一头走到另一头后,他将被传送到过去的某个时刻。FJ 的每个农场包括

    N(1<=N<=500)块按1..N 编号的草地、M(1<=M<=2500)条草地间的道路以及W(1<=W<=200)

    个虫洞。

    FJ 一直以来就渴望进行时间旅行,于是他开始做如下的打算:从某块草地出发,穿

    过一些道路以及一些虫洞,最终回到他出发的草地。这样,他说不定能碰见过去的自

    己:) 。

    请你帮FJ 算一下,他是否可能找到这样的一条路。当然,FJ 会给你他的所有

    F(1<=F<=5)个农场的完整的地图。没有哪条道路上需要花的时间超过10,000 秒,同时,

    也没有哪个虫洞能把FJ 带回10,000 秒以前。

    程序名: wormhole

    输入格式:

    • 第1 行: 一个正整数F,即农场总数。以下依次描述各个农场的地图

    • 每个农场描述的第1 行:三个用空格隔开的整数,N、M 和W

    • 每个农场描述的第2..M+1 行:每行包含三个用空格隔开的整数S、E、T,表示

    编号为S 的草地和编号为E 的草地边有一条双向道路,通过它所花费的时间为T 秒。两

    块草地间可能有多条道路

    • 每个农场描述的第M+2..M+W+1 行:每行包含三个用空格隔开的整数S、E、T,

    描述了一个起点编号为S、终点编号为E 的虫洞。穿过这个虫洞后,FJ 可以回到T 秒之

    前 输入样例(wormhole.in):

    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

    输入说明:

    FJ 交给你两个农场的地图。第一个农场里有三条道路以及一个虫洞,第二个农场里

    有两条道路和一个虫洞。

    输出格式:

    • 第1..F 行: 对于每个农场,如果FJ 可以实现他回到过去的愿望,输出"YES",

    否则输出"NO"(不含引号)。

    输出样例(wormhole.out):

    NO
    YES

    输出说明:

    在农场1 中,FJ 无法完成他期望的时间旅行。

    在农场2 中,FJ 可以沿路线1->2->3->1 旅行,这样他能在离开1 号草地前一秒回

    到1 号草地。当然,从这条路线上的其他草地出发,也能达到目的。

    这道题简单来说就是判断图内是否存在负环;

    判断负环方法:拓扑排序或spfa

    spfa判断负环:如果任意一条边被修改大于n次,就代表这个图内一定存在至少一个负环。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define man 1000010
     4 #define ll int
     5 struct edge 
     6 {
     7     int next,dis,to;
     8     }e[man<<2];
     9 ll head[man<<2],num=0,cnt[man<<1];
    10 bool vis[man];
    11 ll dis[man<<1],t,n,m,w;
    12 inline void add(ll from,ll to,ll dis)
    13 {
    14     e[++num].next=head[from];
    15     e[num].to=to;
    16     e[num].dis=dis;
    17     head[from]=num;
    18     }
    19 inline void clear()
    20 {
    21     memset(head,0,sizeof(head));
    22     memset(e,0,sizeof(e));
    23     memset(cnt,0,sizeof(cnt));
    24     num=0;
    25     }
    26 inline bool spfa(ll s)
    27 {
    28     memset(vis,0,sizeof(vis));
    29     memset(dis,0x7f,sizeof(dis));
    30     queue<int >q;
    31     q.push(s);dis[s]=0;vis[s]=1;
    32     do
    33     {
    34         int u=q.front();q.pop();
    35         vis[u]=0;
    36         for(int i=head[u];i;i=e[i].next)
    37         {
    38             ll to=e[i].to;
    39             if(dis[to]>dis[u]+e[i].dis)
    40             {    dis[to]=dis[u]+e[i].dis;
    41                 if(!vis[to])
    42                 {
    43                     q.push(to);
    44                     vis[to]=1;
    45                     cnt[to]++;
    46                     }
    47                 if(cnt[to]>n) return 1;
    48                 }            
    49             }
    50         }while(q.size());
    51     return 0;
    52     }
    53 int main()
    54 {
    55     ios::sync_with_stdio(false);
    56     cin>>t;
    57     while(t--)
    58     {
    59         clear();
    60         cin>>n>>m>>w;
    61         for(int i=1,x,y,z;i<=m;i++)
    62         {    cin>>x>>y>>z;
    63             add(x,y,z);add(y,x,z);
    64             }
    65         for(int i=1,x,y,z;i<=w;i++)
    66         {    cin>>x>>y>>z;
    67             add(x,y,-z);
    68             }
    69         if(spfa(1)==1) cout<<"YES"<<endl;
    70         else cout<<"NO"<<endl;
    71         }
    72     return 0;
    73     }

    拓扑排序:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 int t,n,m,w,x,y,z,num=0,dis[10010];
     7 bool flag;
     8 struct star{
     9     int from,to,dis;
    10 }e[10010];
    11 void add(int from, int to, int dis){
    12     e[++num].from=from;
    13     e[num].to=to;
    14     e[num].dis=dis;
    15 }
    16 bool topsort(){
    17     memset(dis,0x7f,sizeof(dis));
    18     dis[1]=0;   
    19     for(int i=1;i<=n;i++){
    20         flag=0;
    21         for(int j=1;j<=num;j++)
    22             if(dis[e[j].to]>dis[e[j].from]+e[j].dis){
    23                 flag=1;
    24                 dis[e[j].to]=dis[e[j].from]+e[j].dis;
    25             }
    26         if(!flag)return 0;
    27     }
    28     return 1;
    29 }
    30 int main(){
    31     scanf("%d",&t);
    32     for(int i=1;i<=t;i++){
    33         num=0;
    34         scanf("%d%d%d",&n,&m,&w);
    35         for(int j=1;j<=m;j++){
    36             scanf("%d%d%d",&x,&y,&z);
    37             add(x,y,z);add(y,x,z);
    38         }
    39         for(int j=1;j<=w;j++){
    40             scanf("%d%d%d",&x,&y,&z);
    41             add(x,y,-z);
    42         }
    43         if(topsort())printf("YES
    ");
    44         else printf("NO
    ");
    45     }
    46     return 0;
    47 }
  • 相关阅读:
    Linux命令可以在后台运行,不随shell的关闭而关闭
    Linux系统创建python虚拟环境
    crontab定时任务不执行的一些原因总结
    解决ubuntu下定时任务不执行问题
    18-crm项目-kingadmin,完成crm用户认证登陆
    17-crm项目-kingadmin,前端展示数据库中不存在的字段
    16-crm项目-kingadmin,权限管理
    15-crm项目-kingadmin,自定义用户认证
    14-crm项目-kingadmin,动态url菜单优化
    记录安全问题---2020年9月24号
  • 原文地址:https://www.cnblogs.com/Slager-Z/p/7674940.html
Copyright © 2020-2023  润新知