标签:
连通图 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Description
Input
Output
Sample Input
Sample Output
#include<iostream> #include<vector> #include<cstring> #include<algorithm> #include<cstdio> #include<stack> #include<cmath> using namespace std; #define N 10008 int n, m, cnt, num, top, Time; // Time用来计量时间,top用来控制stackk数组的下标 int dfn[N], low[N], stackk[N]; // dfn数组存到达下标的最小时间,low存下标可以走到的最小的点,stackk是自己建的栈,用来存深搜先后进入的点 bool instack[N]; // 判断是否进栈 vector<vector<int> > G; void init() // 初始化 { G.clear(); G.resize(n+1); memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(stackk, 0, sizeof(stackk)); memset(instack, false, sizeof(instack)); cnt = num = top = Time = 0; } void Tarjan(int u) // 从1点开始进栈,进栈一次Time更新 { low[u] = dfn[u] = ++Time; stackk[top++] = u; instack[u] = true; // 已经进栈就标记true int len = G[u].size(), v; for(int i = 0; i < len; i++) { v = G[u][i]; // 与进栈的点所连接的点 if(!dfn[v]) // 如果这个点还没有被访问过,就把这个点遍历,low随之更新,是原先值和连接的这个值的low的最小值,因为low是指下标所能到的最小的点 { Tarjan(v); low[u] = min(low[u], low[v]); } else if(instack[v]) // 如果已经进栈,就直接判断low的取值就行了, low[u] = min(low[u], dfn[v]); } if(low[u] == dfn[u]) // 如果两个点的第一次到的时间值dfn和可以到的最小值dfn一样,说明不能再往下走了,这个连通图结束,开始出栈 { do { num++; // 出栈一个数num++,计量出栈总数 v = stackk[--top]; // v用来存出栈的数,top--, instack[v] = false; // 出栈置为false,虽然对本题没多大用 }while(u != v); // 当出栈是u时,出栈结束 cnt++; // 每 一次出栈,即每一个连通图,cnt++, } } void slove() { Tarjan(1); if(cnt == 1 && num == n) // 如果cnt等于1,就是就一个连通图。而且连通图内的总数是n,即把每个数都连接在内了,那么久是一个连通图,满足题意 puts("Yes"); else puts("No"); } int main() { while(scanf("%d%d", &n, &m), n+m) { int a, b; init(); while(m--) { scanf("%d%d", &a, &b); G[a].push_back(b); // } slove(); } return 0; }
标签:
原文地址:http://www.cnblogs.com/Tinamei/p/4705308.html