http://poj.org/problem?id=2762 为什么我的就一直是RE啊?费解!! /* 题意:给出n个点和m条边,接着给出直接相连的边(注意是有向边),求解任意x,y两点间是否存在x可到达y或者y可 到达x,如果任意x和y都满足这样的条件就输出"Yes",否则输出"No". 先求解出该有向图的强连通分量,然后根据求解出来的强连通分量进行缩点重新建图, 那么问题就转换为求解在新图中是否存在一条能走完所有的顶点的路径,这时可以对缩点后的新图进行拓扑排序, 看拓扑排序是否可以成功进行(可以通过在拓扑排序的过程中入度为0的顶点个数来进行判断), 如果存在拓扑排序并且是唯一的话说明缩点后的新图存在一条能走完所有顶点的路径. 考点:强连通、拓扑排序过程,返回是否成功,stack存拓扑排序的结果 */ #include<iostream> #include<vector> using namespace std; #define MAXN 1010 int n, m; int dfn[MAXN], low[MAXN];//dfn[i]表示i的搜索次序,low[i]表示节点i能回溯到最早的节点 vector<int> graph[MAXN];//用来储存图 int stack[MAXN];//用来搜索时入栈 bool visit[MAXN], instack[MAXN];//visit用来标记是否已访问,instack[i]标记是否在堆栈中 int index, top;// int cnt;//强连通分支的数量 int belong[MAXN]; int degree[MAXN]; vector<int> newgraph[MAXN]; inline int min(int x, int y) { return x < y ? x : y; } void dfs(int u) { int i, v; dfn[u] = low[u] = index++; stack[top++] = u; instack[u] = true; visit[u] = true; for(i=0; i<graph[u].size(); i++) { v = graph[u][i]; if(!visit[v])//如果还未访问 { dfs(v); low[u] = min(low[u], low[v]);//更新low[u] 的值 } else if(instack[v])//如果还在堆栈中 low[u] = min(low[u], dfn[v]); } if(dfn[u] == low[u])//找到强连通分支的根节点 { ++cnt; // belong[u] = cnt; do { v = stack[top--]; belong[v] = cnt; instack[v] = false; }while(u != v); } } void tarjan()//tanjan算法 { int i; top = 0; cnt = 0; index = 1; memset(visit, 0, sizeof(visit)); memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(instack, 0, sizeof(instack)); memset(belong, 0, sizeof(belong)); for(i=1; i<=n; i++) if(!dfn[i]) dfs(i); } int find_top() { int i, k; int sum = 0; for(i=1; i<=cnt; i++) { if(degree[i] == 0) { sum++; k = i; } } if(sum == 1) return k; else return 0; } bool topsort()//拓扑排序过程,返回是否成功,stack存拓扑排序的结果 { memset(stack, 0, sizeof(stack)); int u; while(u=find_top()) { stack[++stack[0]] = u; degree[u] = -1; for(int i=0; i<newgraph[u].size(); i++) { int v = newgraph[u][i]; degree[v]--; } } if(stack[0] == cnt) return true; else return false; } int main() { freopen("in.txt", "r", stdin); int i, j, t; scanf("%d", &t); while(t--) { scanf("%d %d", &n, &m); for(i=0; i<=n; i++) { graph[i].clear(); newgraph[i].clear(); degree[i] = 0;//入度为0 } int u, v; for(i=0; i<m; i++) { scanf("%d %d", &u, &v); graph[u].push_back(v); } tarjan(); // for(i=1; i<=n; i++) // printf("%d/n", belong[i]); if(cnt == 1) { printf("Yes/n"); continue; } //建立新图newgraph for(i=1; i<=n; i++) { for(j=0; j<graph[i].size(); j++) { int a, b; a = belong[i]; b = belong[graph[i][j]]; if(a != b)//不在同一强连通分支中 { newgraph[a].push_back(b); degree[b]++; } } } bool flag = false; int sum = 0; for(i=1; i<=cnt; i++)//求新图中入度为0的个数 { if(!degree[i]) { sum++; } } if(sum > 1) flag = false;//如果大于1,则不满足 else if(topsort()) flag = true; if(flag) printf("Yes/n"); else printf("No/n"); } return 0; }