hdu - 3594 Cactus (强连通)
2015-08-14 20:05
357 查看
http://acm.hdu.edu.cn/showproblem.php?pid=3594
判断给定的图是否是强连通的,并且每条边都只属于一个连通分量.
判断强连通只需要判断缩点之后顶点数是否为1即可,
然后在缩点的过程中,如果已经产生环,并且当前结点的父节点还有父节点,则必定有多个环,
最后还要判断每个结点都要只属于一个联通分量,否则不符合要求.
判断给定的图是否是强连通的,并且每条边都只属于一个连通分量.
判断强连通只需要判断缩点之后顶点数是否为1即可,
然后在缩点的过程中,如果已经产生环,并且当前结点的父节点还有父节点,则必定有多个环,
最后还要判断每个结点都要只属于一个联通分量,否则不符合要求.
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define ll long long #define inf 0x7f7f7f7f #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("a.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); using namespace std; #define N 20100 //N为最大点数 #define M 50100 //M为最大边数 int n, m;//n m 为点数和边数 struct Edge{ int from, to, nex; bool sign;//是否为桥 }edge[M<<1]; int head , edgenum; void add(int u, int v){//边的起点和终点 Edge E={u, v, head[u], false}; edge[edgenum] = E; head[u] = edgenum++; } //DNF[i]表示遍历到第i点时,是第几次dfs //Low[u] 表示 以u点为父节点的 子树 能连接到 [栈中] 最上端的点 的DFN值(换句话说,是最小的DFN,因为最上端的DFN是最小的嘛) int DFN , Low , Stack , top, Time; //Low[u]是点集{u点及以u点为根的子树} 中(所有反向弧)能指向的(离根最近的祖先v) 的DFN[v]值(即v点时间戳) int taj;//连通分支标号,从1开始 int Belong ;//Belong[i] 表示i点属于的连通分支 bool Instack ,flag; vector<int> bcc ; //标号从1开始 void tarjan(int u ,int fa){ DFN[u] = Low[u] = ++ Time ; Stack[top ++ ] = u ; Instack[u] = 1 ; for (int i = head[u] ; ~i ; i = edge[i].nex ){ int v = edge[i].to ; if(DFN[v] == -1) { tarjan(v , u) ; Low[u] = min(Low[u] ,Low[v]) ; if(DFN[u] < Low[v]) { edge[i].sign = 1;//为割桥 } } else if(Instack[v]) { Low[u] = min(Low[u] ,DFN[v]) ; if(DFN[v]!=Low[v]) flag=1; //父节点还不是根节点 } } if(Low[u] == DFN[u]){ int now; taj ++ ; bcc[taj].clear(); do{ now = Stack[-- top] ; Instack[now] = 0 ; if(Belong[now]!=-1) flag=1; //每个节点都要只属于一个联通分量 Belong [now] = taj ; bcc[taj].push_back(now); }while(now != u) ; } } void tarjan_init(int all){ memset(DFN, -1, sizeof(DFN)); memset(Instack, 0, sizeof(Instack)); memset(Belong,-1,sizeof(Belong)); top = Time = taj = 0; for(int i=1;i<=all;i++)if(DFN[i]==-1 )tarjan(i, i); //注意开始点标!!! } vector<int>G ; int du ; void suodian(){ memset(du, 0, sizeof(du)); for(int i = 1; i <= taj; i++)G[i].clear(); for(int i = 0; i < edgenum; i++){ int u = Belong[edge[i].from], v = Belong[edge[i].to]; if(u!=v) { G[u].push_back(v), du[v]++; // printf("%d %d\n",u,v); } } } void init(){memset(head, -1, sizeof(head)); edgenum=0;} int main() { //Read(); int t,a,b; scanf("%d",&t); while(t--) { scanf("%d",&n); init(); flag=0; while(1) { scanf("%d%d",&a,&b); if(a==0&&b==0) break; add(a+1,b+1); } tarjan_init(n); suodian(); if(taj==1&&flag==0) puts("YES"); else puts("NO"); } return 0; }
相关文章推荐
- 确定比赛名次--hdoj
- ExecutorService常用方法和newFixedThreadPool创建固定大小的线程池
- HDU-2647 Reward(拓扑排序)
- J - Guilty Prince
- OC - ExtensionAndCategory
- (2)华为机试 ——消消乐
- hdu 3594 Cactus (仙人掌图判定/SCC)
- Android笔记_ContentProvider
- 确定比赛名次--hdoj
- c语言中malloc和calloc比较
- 树形dp
- asp.net mvc AjaxBeginForm使用
- Android笔记_数据存储
- Codeforces 570D TREE REQUESTS dfs序+树状数组
- H5填坑笔记--持续更新
- oracle TNS-03505: 无法解析名称错误
- android /linux休眠与唤醒(二)
- HIT 2060 Fibonacci Problem Again(矩阵乘法)
- 浅谈Javascript 中几种克隆(clone)方式
- Eclipse常用快捷键