2015-03-26 20:55:52
思路:题目大意是给出一个有向图,给出起点和终点,让你求出两种点:
(1)任何从起点->终点的路径都必须经过的点。(2)该点将图分为两部分,(起点->该点)和(该点->终点)两个部分,且两个部分没有边相连。
考虑:显然(2)点必然是(1)点,所以我们先求(1)点,方法很简单,枚举删除每个点,如果删除后从起点出发走不到终点了,那么该点符合(1)的性质。
这个过程从起点floodfill(bfs)可以实现。求(2)点稍微复杂点,也是枚举每个点,假设按照这个点来分割图,显然该点出边对应的另一些点V1,入边对应的
另一些点V2分别属于两个部分,那么我们就可以从点集V2出发floodfill(bfs),把遍历到的点标记掉,最后判断是否有点集V1里的点被标记掉。需要注意的是:
此时应该把图看做无向图来做,我们需要判断的是两个部分是否有边相连,而不是两个有向子图是否连通(思考)。
1 /* 2 ID:naturec1 3 PROG: race3 4 LANG: C++ 5 */ 6 #include <cstdio> 7 #include <cstring> 8 #include <cstdlib> 9 #include <cmath> 10 #include <vector> 11 #include <map> 12 #include <set> 13 #include <stack> 14 #include <queue> 15 #include <string> 16 #include <iostream> 17 #include <algorithm> 18 using namespace std; 19 20 #define MEM(a,b) memset(a,b,sizeof(a)) 21 #define REP(i,n) for(int i=1;i<=(n);++i) 22 #define REV(i,n) for(int i=(n);i>=1;--i) 23 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 24 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i) 25 #define getmid(l,r) ((l) + ((r) - (l)) / 2) 26 #define MP(a,b) make_pair(a,b) 27 28 typedef long long ll; 29 typedef pair<int,int> pii; 30 const int INF = (1 << 30) - 1; 31 const int MAXN = 210; 32 33 int g[MAXN][MAXN]; 34 int vis[MAXN],st,ed; 35 vector<int> ans1,ans2; 36 37 bool Check1(int p){ 38 queue<int> Q; 39 while(!Q.empty()) Q.pop(); 40 Q.push(st); 41 MEM(vis,0); 42 vis[st] = 1; 43 while(!Q.empty()){ 44 int x = Q.front(); Q.pop(); 45 for(int i = st + 1; i <= ed; ++i) if(g[x][i]){ 46 if(i == p) continue; 47 if(!vis[i]){ 48 vis[i] = 1; 49 Q.push(i); 50 } 51 } 52 } 53 return vis[ed] == 0; 54 } 55 56 int fa[MAXN]; 57 58 bool Check2(int p){ 59 queue<int> Q; 60 while(!Q.empty()) Q.pop(); 61 MEM(vis,0); 62 vis[p] = 1; 63 for(int i = st; i <= ed; ++i) if(!vis[i] && g[p][i]){ 64 vis[i] = 1; 65 Q.push(i); 66 } 67 while(!Q.empty()){ 68 int x = Q.front(); Q.pop(); 69 for(int i = st; i <= ed; ++i) if(g[x][i] || g[i][x]){ 70 if(i == p) continue; 71 if(!vis[i]){ 72 vis[i] = 1; 73 Q.push(i); 74 } 75 } 76 } 77 for(int i = st; i <= ed; ++i) if(vis[i] == 0) return true; 78 return false; 79 } 80 81 int main(){ 82 freopen("race3.in","r",stdin); 83 freopen("race3.out","w",stdout); 84 int tot = 0; 85 int a,b; 86 while(scanf("%d",&a) != EOF){ 87 if(a == -1) break; 88 if(a == -2){ 89 tot++; 90 continue; 91 } 92 g[tot][a] = 1; 93 while(cin >> a && a != -2) g[tot][a] = 1; 94 tot++; 95 } 96 st = 0; 97 ed = tot - 1; 98 REP(i,ed - 1){ 99 if(Check1(i)){ 100 ans1.push_back(i); 101 if(Check2(i)) ans2.push_back(i); 102 } 103 } 104 printf("%d",(int)ans1.size()); 105 for(int i = 0; i < ans1.size(); ++i) printf(" %d",ans1[i]); 106 puts(""); 107 printf("%d",(int)ans2.size()); 108 for(int i = 0; i < ans2.size(); ++i) printf(" %d",ans2[i]); 109 puts(""); 110 return 0; 111 }