Educational Codeforces Round 10 E

题目链接:http://codeforces.com/contest/652/problem/E

给你n个点m个边,x和y双向连接,要是z是1表示这条边上有宝藏,0则没有,最后给你起点和终点,问你要是到从起点到终点要是中间遇到宝藏就输出YES,否则就输出NO。

每条边只能经过一次,而且这个图保证连通的。

我用tarjan强连通缩点,把这个图变成一棵树,要是起点终点在一个连通分量里且分量里的边有宝藏,那么就输出YES。否则,就找起点到终点直接的路有没有宝藏,因为缩点之后是一棵树,所以起点和终点只有一条路。那我从起点dfs一遍,par[i]记录的是i前驱节点。那我之后就从终点反向遍历这条路,要是路上有宝藏,就输出YES。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <vector>
  5 #include <set>
  6 using namespace std;
  7 const int MAXN = 3e5 + 10;
  8 typedef pair <int , int> P;
  9 struct data {
 10     int next , to , art;
 11 }edge[MAXN * 2];
 12 int head[MAXN] , low[MAXN] , dfn[MAXN] , st[MAXN] , block[MAXN] , p[MAXN];
 13 int top , ord , sccnum , end_point , cont;
 14 bool instack[MAXN] , vis[MAXN] , ok , res;
 15 vector <P> G[MAXN];
 16 
 17 void init() {
 18     memset(head , -1 , sizeof(head));
 19 }
 20 
 21 inline void add(int u , int v , int art) {
 22     edge[cont].next = head[u];
 23     edge[cont].to = v;
 24     edge[cont].art = art;
 25     head[u] = cont++;
 26 }
 27 
 28 void tarjan(int u , int par) {
 29     low[u] = dfn[u] = ++ord;
 30     st[++top] = u;
 31     instack[u] = true;
 32     for(int i = head[u] ; ~i ; i = edge[i].next) {
 33         int v = edge[i].to;
 34         if(v == par)
 35             continue;
 36         if(!dfn[v]) {
 37             tarjan(v , u);
 38             low[u] = min(low[v] , low[u]);
 39         }
 40         else if(instack[v]) {
 41             low[u] = min(low[u] , dfn[v]);
 42         }
 43     }
 44     if(dfn[u] == low[u]) {
 45         sccnum++;
 46         int v;
 47         do {
 48             v = st[top--];
 49             instack[v] = false;
 50             block[v] = sccnum;
 51         }while(u != v);
 52     }
 53 }
 54 
 55 void dfs(int u , int par) {
 56     p[u] = par;
 57     for(int i = 0 ; i < G[u].size() ; i++) {
 58         int v = G[u][i].first;
 59         if(par == v)
 60             continue;
 61         if(G[u][i].second)
 62             vis[v] = true;
 63         dfs(v , u);
 64     }
 65 }
 66 
 67 int main()
 68 {
 69     int n , m , u , v , art , s , e , heheda = 1;
 70     scanf("%d %d" , &n , &m);
 71     init();
 72     for(int i = 0 ; i < m ; i++) {
 73         scanf("%d %d %d" , &u , &v , &art);
 74         add(u , v , art);
 75         add(v , u , art);
 76         if(art == 1)
 77             heheda = 0;
 78     }
 79     scanf("%d %d" , &s , &e);
 80     if(heheda) {
 81         printf("NO
");
 82         return 0;
 83     }
 84     tarjan(1 , -1);
 85     end_point = block[e];
 86     for(int u = 1 ; u <= n ; u++) {
 87         for(int i = head[u] ; ~i ; i = edge[i].next) {
 88             int v = edge[i].to;
 89             if(block[u] != block[v]) {
 90                 G[block[u]].push_back(P(block[v] , edge[i].art));
 91             }
 92             else {
 93                 if(!vis[block[u]])
 94                     vis[block[u]] = (bool)(edge[i].art);
 95             }
 96         }
 97     }
 98     if(block[s] == end_point && vis[block[s]]) {
 99         printf("YES
");
100         return 0;
101     }
102     if(vis[block[s]])
103         res = true;
104     dfs(block[s] , -1);
105     for(int i = end_point ; ~i ; i = p[i]) {
106         if(vis[i])
107             res = true;
108     }
109     if(res)
110         printf("YES
");
111     else
112         printf("NO
");
113 }
原文地址:https://www.cnblogs.com/Recoder/p/5323546.html