程帅霞

不断受挫,不停起身,不断追寻,不止AC~~

导航

Wormholes

While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of FJ's farms comprises N (1 ≤ N ≤ 500) fields conveniently numbered 1..NM (1 ≤ M ≤ 2500) paths, and W (1 ≤ W ≤ 200) wormholes.

As FJ is an avid time-traveling fan, he wants to do the following: start at some field, travel through some paths and wormholes, and return to the starting field a time before his initial departure. Perhaps he will be able to meet himself :) .

To help FJ find out whether this is possible or not, he will supply you with complete maps to F (1 ≤ F ≤ 5) of his farms. No paths will take longer than 10,000 seconds to travel and no wormhole can bring FJ back in time by more than 10,000 seconds.

Input

Line 1: A single integer, FF farm descriptions follow.
Line 1 of each farm: Three space-separated integers respectively: NM, and W
Lines 2..M+1 of each farm: Three space-separated numbers (SET) that describe, respectively: a bidirectional path between S and E that requires T seconds to traverse. Two fields might be connected by more than one path.
Lines M+2..M+W+1 of each farm: Three space-separated numbers (SET) that describe, respectively: A one way path from S to E that also moves the traveler back T seconds.

Output

Lines 1..F: For each farm, output "YES" if FJ can achieve his goal, otherwise output "NO" (do not include the quotes).

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

Hint

For farm 1, FJ cannot travel back in time.
For farm 2, FJ could travel back in time by the cycle 1->2->3->1, arriving back at his starting location 1 second before he leaves. He could start from anywhere on the cycle to accomplish this.

题意:

有n个点,m条普通的双向的路,w条单向的虫洞,问是否能从某个点出发走一些路再回来时回到过去。

即判断是否有负环。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 #include<stack>
 6 #include<algorithm>
 7 #include<cmath>
 8 #include<vector>
 9 #define N 50000//记得开大一点,做的时候开5000RE了好几遍
10 #define inf 0x3f3f3f
11 using namespace std;
12 
13 struct node
14 {
15     int to,w,next;
16 } s[N];
17 
18 int n;
19 int tot;
20 int vis[N];
21 int dis[N];
22 int head[N];
23 int num[N];
24 
25 void add(int u,int v,int w)//记得这个函数存的是边的信息(编号为tot的边的指向以及权值),而不是点的信息,
26 {
27     s[tot].to = v;
28     s[tot].w = w;
29     s[tot].next = head[u];
30     head[u] = tot++;//边的个数
31 }
32 
33 int spfa()
34 {
35     queue<int> q;
36     memset(num,0,sizeof(num));
37     memset(vis,0,sizeof(vis));
38     for(int i = 1; i <= n; i++)//这里初始化可以用memset
39     {
40         dis[i] = inf;
41     }
42     dis[1] = 0;
43     num[1] = 1;
44     vis[1] = 1;
45     q.push(1);
46     while(q.size())
47     {
48         int u = q.front();
49         q.pop();
50         vis[u] = 0;
51         for(int i = head[u]; i != -1; i = s[i].next)
52         {
53             int v = s[i].to;
54             if(dis[v] > dis[u] + s[i].w)
55             {
56                 dis[v] = dis[u] + s[i].w;
57                 if(vis[v] == 0)
58                 {
59                     num[v]++;
60                     if(num[v] >= n)//如果入队次数大于点的个数则存在负环
61                         return 1;
62                     vis[v] = 1;
63                     q.push(v);
64                 }
65             }
66         }
67     }
68     return 0;
69 }
70 
71 int main()
72 {
73     int t,x,y;
74     int u,v,w;
75     scanf("%d",&t);
76     while(t--)
77     {
78         tot = 1;//tot为0或1没差
79         memset(head,-1,sizeof(head));
80         scanf("%d %d %d",&n,&x,&y);
81         while(x--)
82         {
83             scanf("%d %d %d",&u,&v,&w);
84             add(u,v,w);
85             add(v,u,w);
86         }
87         while(y--)
88         {
89             scanf("%d %d %d",&u,&v,&w);
90             add(u,v,w*(-1));
91         }
92         if(spfa())
93             printf("YES\n");
94         else
95             printf("NO\n");
96     }
97     return 0;
98 }

 

 

 

#include<cstdio>
#include<queue>
using namespace std;
const int N = 510;
const int INF = 0x7fffffff;
int g[N][N], n, d[N];
int cnt[N];
bool in_q[N];
//SPFA算法
bool SPFA(int s)
{
    queue<int> q; //建立队列
    for( int i = 1 ; i <= n ; i++ )
    {
        cnt[i] = 0; //初始化扩展计数器
        d[i] = INF; //初始化d值
        in_q[i] = false; //初始化in队列标记
    }
    q.push(s); //起点入队列
    cnt[s]++; //扩展计数器自加
    d[s] = 0; //到起点距离置0
    in_q[s] = true; //标记in队列
    while(!q.empty())
    {
        int v = q.front();
        q.pop(); //队头出队列
        in_q[v] = false; //标记出队列
        for( int i = 1 ; i <= n ; i++ )
        {
            if( g[v][i] < INF && d[v]+g[v][i] < d[i] )
            {
                d[i] = d[v]+g[v][i]; //松弛
                if(!in_q[i]) //如果不在队列中
                {
                    in_q[i] = true; //入队列
                    if( ++cnt[i] >= n )
                        return true;
                    q.push(i);
                }
            }
        }
    }
    return false;
}
int main()
{
    int fn, m, w;
    scanf("%d", &fn);
    while(fn--)
    {
        scanf("%d%d%d", &n, &m, &w);
        for( int i = 1 ; i <= n ; i++ )
            for( int j = i+1 ; j <= n ; j++ )
                g[i][j] = g[j][i] = INF; //初始化邻接矩阵
        while(m--)
        {
            int s, e, t;
            scanf("%d%d%d", &s, &e, &t);
            if( t < g[s][e] ) //处理重边
                g[s][e] = g[e][s] = t;
        }
        while(w--)
        {
            int s, e, t;
            scanf("%d%d%d", &s, &e, &t);
            g[s][e] = -t;
        }
        printf("%s\n", SPFA(1)?"YES":"NO"); //只试起点1
    }
    return 0;
}

 

posted on 2021-01-31 19:24  程帅霞  阅读(102)  评论(0编辑  收藏  举报