poj2767,单向连通图判定,缩点+重新建图+新图DFS
来源:互联网 发布:计算机专业除了编程 编辑:程序博客网 时间:2024/05/22 13:08
/*该题被博客里标记为中等题,30分钟内1A,掌握了算法就简单了,单向连通图判定,单向连通图缩点后必然唯一存在出度为0的点和入度为0的点,并且从入度为0的点出发,可以遍历所有点后到达出度为0点(一条长链),(容易反证),所以缩点后,我重新建图(以前觉得重新建图好麻烦,现在看来SO easy),,对新有向无环图,从入度为0的点做dfs(回溯时要标记回来,因为要所有dfs路线),有一条深度到达强连通分支数即为yes,反之no*/#include<iostream> //297MS, 1A,简单题。#include<vector>#include<cstdio>#include<cstring>#include<stack>using namespace std;int n;int m;const int MAX=1001;vector<vector<int> >edges(MAX); //原图vector<vector<int> >newedge(MAX);//缩点后图int visited[MAX]; //原图tarjanint low[MAX];int dfn[MAX];bool mark[MAX]; //新图dfs标记int Strongly_connected_branch[MAX]; //并为一个强连通,标记为1.2.3...int num;int times; stack<int>s; bool instack[MAX];int ind[MAX]; //入度数组void tarjan(int u){ low[u]=dfn[u]=times++; instack[u]=1; s.push(u); int len=edges[u].size(); for(int i=0;i<len;i++) { int v=edges[u][i]; if(visited[v]==0) { visited[v]=1; tarjan(v); if(low[u]>low[v])low[u]=low[v]; } else if(instack[v]&&low[u]>dfn[v]) //有向图,要问是否在栈中,后向边,V为U某个祖先 { low[u]=dfn[v]; } } if(dfn[u]==low[u]) //在一个SCC { num++;int temp; do { temp=s.top(); instack[temp]=0; s.pop(); Strongly_connected_branch[temp]=num; } while(temp!=u); }}bool is_no; void dfs(int u,int depth) //新图的dfs{ if(depth==num)is_no=true; int len=newedge[u].size(); for(int i=0;i<len;i++) { int v=newedge[u][i]; if(mark[v]==0) { mark[v]=1; dfs(v,depth+1); mark[v]=0; } }}void readin(){ scanf("%d%d",&n,&m); int from,to; for(int i=1;i<=m;i++) { scanf("%d%d",&from,&to); edges[from].push_back(to); }}void initialize() //初始化{ is_no=num=times=0; for(int i=0;i<=n;i++) { ind[i]=0; mark[i]=instack[i]=low[i]=dfn[i]=visited[i]=0; edges[i].clear(); newedge[i].clear(); Strongly_connected_branch[i]=-1; }}void solve(){ for(int i=1;i<=n;i++) if(visited[i]==0) { visited[i]=1; tarjan(i); } for(int i=1;i<=n;i++) //重新建图,不在同一个SCB的边留下即可。 { int len=edges[i].size(); for(int j=0;j<len;j++) { int v=edges[i][j]; if(Strongly_connected_branch[v]!=Strongly_connected_branch[i]) //注意用SCB序号作代表元(新节点)来重新建图 { ind[Strongly_connected_branch[v]]++; newedge[Strongly_connected_branch[i]].push_back(Strongly_connected_branch[v]); } } } int is_0ind; for(int i=1;i<=num;i++) //找到入度为0的点,做起点dfs { if(ind[i]==0)is_0ind=i; } mark[is_0ind]=1; dfs(is_0ind,1); if(is_no)printf("Yes\n"); else printf("No\n");}int main(){ int tcase; scanf("%d",&tcase); while(tcase--) { initialize(); readin(); solve(); } return 0;}
0 0
- poj2767,单向连通图判定,缩点+重新建图+新图DFS
- POJ2762判断图是否单向连通,缩点+dfs
- hdu1116 欧拉图的判定(点的度数的判定+用非递归的路径压缩的并查集/dfs对连通图的判定)
- poj 2762 Going from u to v or from v to u? 单向连通图判定
- 判断强连通图、单向连通图、弱连通图
- zoj2412 dfs连通图
- DFS连通图
- 二分图判定 DFS版
- 无向图强连通分量缩点+DFS序 codeforces555E Case of Computer Network
- hdu 1269 强连通图的判定
- hdu 1269 强连通图的判定
- eoj 1816. 连通(无向图是否连通判定)
- POJ 2762 证明是否为单向连通图 强连通缩点+类拓扑排序
- POJ 2762 单向的连通图
- 图 dfs遍历连通块
- SCC重新建图
- HDU 3836--Equivalent Sets【求有向图最少增加多少边使图强连通 && Scc缩点新建图】
- 【连通图|强连通+缩点】POJ-2186 Popular Cows
- 为operamasks增加HTML扩展方式的组件调用
- 分享一些大牛的Android博客
- ubuntu10.4安装交叉编译器arm-none-linux-gnueabi-gcc
- .NET Framework简介
- 虚拟机QT编译环境配置
- poj2767,单向连通图判定,缩点+重新建图+新图DFS
- linux中tomcat启动错误:java.net.BindException: Permission denied <null>:80
- java io ---文件读取为byte数组
- ubuntu 11.04 中安装 opencv 2.3
- 面向对象基础知识(1)- 初步认识
- IOCP模型与网络编程
- 动态树 bzoj2049
- Windows下Android开发环境搭建和配置
- 九度oj 题目1030:毕业bg