USACO race3
这个题的第一问的意思是让你求出从0 走到 N必须走的点集的集合, 第二问的意识是判断被一个点分开的两个子图有没有公共边, 对于第一问我们去掉i后如果发现无法从0走向N那么i就是要求得点, 第二问可以用种子填充, 如果发现有一些点被染到了两种颜色那么这个点就是不满足条件的点。代码如下:
/* ID: m1500293 LANG: C++ PROG: race3 */ #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; vector<int> G[55]; int r1[100], nr1; int r2[100], nr2; int vis[100], ed; bool dfs(int u, int ii) //当前在u 不通过ii能否到达终点 { if(u==ed) return true; bool res = false; vis[u] = true; for(int i=0; i<G[u].size(); i++) { int v = G[u][i]; if(!vis[v] && v!=ii) res = res || dfs(v, ii); } return res; } bool judge(int i) { memset(vis, 0, sizeof(vis)); return !dfs(0, i); } bool floodfill(int u, int ii, int col) //不经过ii点的染色 { if(vis[u] && vis[u]!=col) return false; vis[u] = col; bool res = true; for(int i=0; i<G[u].size(); i++) { int v = G[u][i]; if(v!=ii && vis[v]!=col) res = res && floodfill(v, ii, col); } return res; } bool judge1(int i) //去掉点ii后进行种子填充 { memset(vis, 0, sizeof(vis)); floodfill(i, -1, 1); return floodfill(0, i, 2); } int main() { freopen("race3.in", "r", stdin); freopen("race3.out", "w", stdout); int u = 0; while(1) { int t; scanf("%d", &t); if(t == -1) break; while(t!=-2) { G[u].push_back(t); scanf("%d", &t); } if(t==-2) { u++; continue; } } --u; //一共0-u个点 nr1 = 0; ed = u; for(int i=1; i<u; i++) { if(judge(i)) r1[nr1++] = i; } if(nr1 == 0) printf("%d\n", nr1); else { printf("%d ", nr1); for(int i=0; i<nr1; i++) printf("%d%c", r1[i], i==nr1-1?'\n':' '); } nr2 = 0; for(int i=0; i<nr1; i++) { if(judge1(r1[i])) r2[nr2++] = r1[i]; } if(nr2 == 0) printf("%d\n", nr2); else { printf("%d ", nr2); for(int i=0; i<nr2; i++) printf("%d%c", r2[i], i==nr2-1?'\n':' '); } return 0; }