POJ 2762 Going from u to v or from v to u?
来源:互联网 发布:淘宝网哪家蜜蜡保真 编辑:程序博客网 时间:2024/05/29 16:41
题目链接:http://poj.org/problem?id=2762
题意:给出一个图及其相连的边,判断是否任意两点之间都是相通的(能从x到y或者能从y到x)。
题解:可以知道每个强连通分中的点必然都能够相互到达,所以先对图进行缩点,缩点之后是一个有向无环图DAG,构造新图,任意两个点相互可达转化为任意两个连通分量相互可达,即新图中任意两个点可达。
对新图进行拓扑排序,排序之后如果任意相邻两点之间存在边,相当于存在一条从一个点途径其余所有点到达另一个点的一条“链”,则这个新图任意两点都是是相互可达的。
想象一下拓扑排序后相邻两点不存在边的情况,其实就是当寻找当前入度为0的点的时候找到的点不止一个,则这两个点必定不连通。如下图,当1,2排序之后,发现有两个入度为0的点3和4,则这两个点排完序之后虽然相邻,但是并不相通。
但是其实这道题不用实际的拓扑排序,因为我们知道其实Tarjan算法求出的连通分量的顺序就是这个新图的拓扑排序的逆。(可以看这篇博客)
代码:
用拓扑排序。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<stack>using namespace std;const int MAX=1000+10;vector<int> g[MAX];stack<int> st;int dfn[MAX],low[MAX],instack[MAX];int sccno[MAX];int dfs_cnt,scc_cnt;int G[MAX][MAX];int in[MAX];int topo[MAX];int n,m;void dfs(int u){dfn[u]=low[u]=++dfs_cnt;st.push(u);instack[u]=1;for(int i=0;i<g[u].size();i++){int v=g[u][i];if(!dfn[v]){dfs(v);low[u]=min(low[u],low[v]);}else if(instack[v]){low[u]=min(low[u],dfn[v]);}}if(dfn[u]==low[u]){int v;scc_cnt++;do{v=st.top();st.pop();instack[v]=0;sccno[v]=scc_cnt;}while(u!=v);}}void tarjan(){dfs_cnt=scc_cnt=0;memset(dfn,0,sizeof(dfn));memset(instack,0,sizeof(instack));memset(sccno,0,sizeof(sccno));while(!st.empty()) st.pop();for(int i=1;i<=n;i++){if(!dfn[i]) dfs(i); }}void toposort(){for(int i=1;i<=scc_cnt;i++){for(int j=1;j<=scc_cnt;j++){in[j]+=G[i][j];}}for(int k=0;k<scc_cnt;k++){int i,j;for(i=1;in[i]&&i<=scc_cnt;i++);if(i>scc_cnt) return ;topo[k]=i;in[i]=-1;for(j=1;j<=scc_cnt;j++){if(G[i][j]){in[j]--;}}}}int main(){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);int T;scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);memset(G,0,sizeof(G));memset(in,0,sizeof(in));memset(topo,0,sizeof(topo));for(int i=1;i<=n;i++)g[i].clear();for(int i=0;i<m;i++){int a,b;scanf("%d%d",&a,&b);g[a].push_back(b);}tarjan();for(int i=1;i<=n;i++)for(int k=0;k<g[i].size();k++){int j=g[i][k];if(sccno[i]!=sccno[j])G[sccno[i]][sccno[j]]=1;}toposort();int flag=1;for(int i=1;i<scc_cnt;i++){if(!G[topo[i-1]][topo[i]]){flag=0;break;}}printf("%s\n",flag?"Yes":"No");}return 0;}不用拓扑排序,直接判断:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <stack>using namespace std;const int MAX=1000+10;vector<int> g[MAX];stack<int> st;int dfn[MAX],low[MAX],instack[MAX];int sccno[MAX];int dfs_cnt,scc_cnt;int G[MAX][MAX];int n,m;void dfs(int u){dfn[u]=low[u]=++dfs_cnt;st.push(u);instack[u]=1;for(int i=0;i<g[u].size();i++){int v=g[u][i];if(!dfn[v]){dfs(v);low[u]=min(low[u],low[v]);}else if(instack[v]){low[u]=min(low[u],dfn[v]);}}if(dfn[u]==low[u]){int v;scc_cnt++;do{v=st.top();st.pop();instack[v]=0;sccno[v]=scc_cnt;}while(u!=v);}}void tarjan(){dfs_cnt=scc_cnt=0;memset(dfn,0,sizeof(dfn));memset(instack,0,sizeof(instack));memset(sccno,0,sizeof(sccno));while(!st.empty()) st.pop();for(int i=1;i<=n;i++){if(!dfn[i]) dfs(i); }}int main(){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);int T;scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);memset(G,0,sizeof(G));for(int i=1;i<=n;i++)g[i].clear();for(int i=0;i<m;i++){int a,b;scanf("%d%d",&a,&b);g[a].push_back(b);}tarjan();for(int i=1;i<=n;i++)for(int k=0;k<g[i].size();k++){int j=g[i][k];if(sccno[i]!=sccno[j])G[sccno[i]][sccno[j]]=1;}int flag=1;for(int i=2;i<=scc_cnt;i++){if(!G[i][i-1]){flag=0;break;}}printf("%s\n",flag?"Yes":"No");}return 0;}
0 0
- POJ 2762 Going from u to v or from v to u? (Tarjan) - from lanshui_Yang
- POJ 2762 Going from u to v or from v to u?
- poj 2762 Going from u to v or from v to u?
- poj 2762 Going from u to v or from v to u?
- poj 2762 Going from u to v or from v to u
- poj 2762 Going from u to v or from v to u?
- poj 2762 Going from u to v or from v to u?
- POJ 2762 Going from u to v or from v to u?(Tarjan)
- poj 2762 Going from u to v or from v to u?
- poj 2762 Going from u to v or from v to u? 强连通最长链
- Poj 2762 Going from u to v or from v to u? (判断图弱连通)
- poj 2762 Going from u to v or from v to u (Kosaraju+缩点+单链图)
- POJ 2762 Going from u to v or from v to u? / 强连通分量&&拓扑
- poj 2762 Going from u to v or from v to u?
- POJ 2762 Going from u to v or from v to u? 强连通+判断链
- poj 2762 Going from u to v or from v to u
- 【POJ】2762 Going from u to v or from v to u? 强连通+最长路
- POJ 2762 Going from u to v or from v to u? (图论-tarjan)
- [Linux] 管道容量以及缓冲区的组成
- 题目14 会场安排问题
- android6.0实现锁屏壁纸
- Java的IO
- jarsigner 给apk签名
- POJ 2762 Going from u to v or from v to u?
- poi读取行数的问题
- cf - 140 C. New Year Snowmen(贪心+优先队列)
- [Objective-C]关联(objc_setAssociatedObject、objc_getAssociatedObject、objc_removeAssociatedObjects)
- java语言基础入门——包装器
- FireBug 使用方法 详解!
- LeetCode-279:Perfect Squares
- PHP4 中文手册
- HDU 2492 Ping pong 树状数组