Neither shaken nor stirred(DFS理解+vector存图)
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=2013
题目理解:
给定n个点的有向图:
下面n行,第一个数字表示点权,后面一个数字m表示有m条边。
起点是1.
对于每个点,输出2个值表示前驱点权1和该点点权2。
1、就是若有多条路径且全为“同一个值”输出“同一个值”,否则输出unknown;
若有一条路径若前驱节点的权值>0,输出前驱结点的权值,否则输出sober;
2、否则若该点点权>0输出该点点权,否则输出前驱点权值(若有多条路径且全为“同一个值”输出“同一个值”,否则输出unknown;
若有一条路径若前驱节点的权值>0,输出前驱结点的权值,否则输出sober)
AC代码+详解
1 /* */ 2 # include <iostream> 3 # include <stdio.h> 4 # include <string.h> 5 # include <algorithm> 6 # include <bitset> 7 # include <ctime> 8 # include <cmath> 9 # include <list> 10 # include <cctype> 11 # include <cassert> 12 # include <iomanip> 13 # include <deque> 14 # include <queue> 15 # include <stack> 16 # include <set> 17 # include <map> 18 # include <vector> 19 using namespace std; 20 21 const int inf=0x3f3f3f3f; 22 const int maxn=2e5+50; 23 int a[maxn]; 24 int zt[maxn]; 25 vector<int>ve[maxn]; 26 27 void dfs(int x, int y)///x此结点,y前驱结点的权值 28 { 29 if( zt[x]==-2 )///有两个前驱,(既然已经判断出有两个前驱,且此路之前来过,就没必要再往下遍历了) 30 return ; 31 32 33 if( !zt[x] )///还没有访问过 34 zt[x] = y;///记录其前驱节点的权值 35 else///已经访问过之后又来访问说明有两个前驱结点了,标记一下 36 zt[x] = -2; 37 38 39 if( a[x] )///此结点的权值不为0 40 y=a[x]; 41 42 43 for( auto it:ve[x] ) 44 { 45 if( zt[it]!=y )///之前的前驱结点的值不为现在前驱结点的值, 46 ///若zt[it]原来为0,说明没有遍历过 47 ///若zt[it]原来为-1,或者是一个正整数 48 ///但之前前驱结点的值与此时前驱节点的值不一样 49 ///那么就再进行一次遍历 50 ///至于具体是什么情况,for有前面的判断决定 51 { 52 dfs(it, y); 53 } 54 } 55 56 } 57 58 int main() 59 { 60 memset(zt, 0, sizeof(zt)); 61 int n; 62 cin>>n; 63 for(int i=1; i<=n; i++ ) 64 { 65 cin>>a[i]; 66 int x; 67 cin>>x; 68 for(int j=1; j<=x; j++ ) 69 { 70 int y; 71 cin>>y; 72 ve[i].push_back(y); 73 } 74 } 75 dfs(1, -1); 76 77 for(int i=1; i<=n; i++ ) 78 { 79 if( zt[i]==-1 ) 80 cout<<"sober "; 81 82 else if( zt[i]==-2 ) 83 cout<<"unknown "; 84 85 else 86 cout<<zt[i]<<' '; 87 88 if( a[i]>0 ) 89 cout<<a[i]<<endl; 90 91 else 92 { 93 if( zt[i]==-1 ) 94 cout<<"sober"<<endl; 95 96 else if( zt[i]==-2 ) 97 cout<<"unknown"<<endl; 98 99 else 100 cout<<zt[i]<<endl; 101 } 102 } 103 return 0; 104 }