标签:
题目链接: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\n"); 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\n"); 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\n"); 111 else 112 printf("NO\n"); 113 }
Educational Codeforces Round 10 E - Pursuit For Artifacts (强联通缩点 + 回溯)
标签:
原文地址:http://www.cnblogs.com/Recoder/p/5323546.html