您的位置:首页 > 编程语言 > Go语言

POJ 2762 Going from u to v or from v to u?

2012-10-31 11:33 477 查看
POJ 2762 Going from u to v or from v to u?

题意:有n个山洞m条路,问任意两点x,y能否存在从x到y或者从y到x。

思路:

1、注意是或而不是和,所以“缩点”后,由于“缩点”内的点相互可达,所以不需要管“缩点”内的点。注意,不是判断强连通的数量为1,而是判断是否是弱连通。

2、如果两点不可达那么在拓扑排序时,该两点谁也不是谁的前驱和后继,所以在拓扑排序时只要同时出现至少两个入度为0的点,那么这些点一定互不可达,所以只要判断拓扑的方式是否唯一即可。

第一种方法:只要用拓扑判断入度为0的点是否为1个,如果有多个,就出现在分叉,不可能从x到y。

第二种方法:从入度为0的点DFS搜索最长能到达的路径如果路径长度等于点数,说明可以从源点访问完所有点。

知识充电:

强连通图:在有向图中, 若对于每一对顶点v1和v2, 都存在一条从v1到v2和从v2到v1的路径,则称此图是强连通图.

弱连通图:将有向图的所有的有向边替换为无向边,所得到的图称为原图的基图。如果一个有向图的基图是连通图,则有向图是弱连通图。

单向连通图:如果有向图中,对于任意节点v1和v2,至少存在从v1到v2和从v2到v1的路径中的一条,则原图为单向连通图。

三者之间的关系是,强连通图必然是单向连通的,单向连通图必然是弱连通图。

CODE:

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

#define MAXN 50010
#define MAXM 100010

struct Edge
{
int v, next;
}edge[MAXM], edge2[MAXM];

int first[MAXN], first2[MAXN],stack[MAXN], ins[MAXN], dfn[MAXN], low[MAXN];
int belong[MAXM];
int ind[MAXN], outd[MAXN], topo[MAXN];

int n, m;
int cnt, cnt2;
int scnt, top, tot;

void init()
{
cnt = 0, cnt2 = 0;
scnt = top = tot = 0;
memset(dfn, 0, sizeof(dfn));
memset(first, -1, sizeof(first));
memset(first2, -1, sizeof(first2));
memset(ins, 0, sizeof(ins));
memset(ind, 0, sizeof(ind));
//memset(outd, 0, sizeof(outd));
//memset(topo, 0, sizeof(topo));
}

void read_graph(int u, int v)
{
edge[cnt].v = v;
edge[cnt].next = first[u];
first[u] = cnt++;
}

void read_graph2(int u, int v) //重构图
{
edge2[cnt2].v = v;
edge2[cnt2].next = first2[u], first2[u] = cnt2++;
}

void dfs(int u)
{
int v;
dfn[u] = low[u] = ++tot;
ins[u] = 1;
stack[top++] = u;
for(int e = first[u]; e != -1; e = edge[e].next)
{
v = edge[e].v;
if(!dfn[v])
{
dfs(v);
low[u] = min(low[u], low[v]);
}
else if(ins[v])
{
low[u] = min(low[u], dfn[v]);
}
}
if(dfn[u] == low[u])
{
scnt++;
do
{
v = stack[--top];
belong[v] = scnt;
ins[v] = 0;
}while(v != u);
}
}

void Tarjan()
{
for(int v = 1; v <= n; v++) if(!dfn[v])
dfs(v);
} //Tarjan

int toposort()
{
queue<int> q;
int tot2 = 0;
for(int i = 1; i <= scnt; i++) if(!ind[i]) q.push(i);
if(q.size() > 1) return 0;
while(!q.empty())
{
int x = q.front(); q.pop();
topo[++tot2] = x;
for(int e = first2[x]; e != -1; e = edge2[e].next)
{
int v = edge2[e].v;
if(--ind[v] == 0)
{
q.push(v);
}
}
if(q.size() > 1) return 0;
}
if(tot2 != scnt) return 0;
else return 1;
} //toposort

void solve()
{
Tarjan();
for(int u = 1; u <= n; u++) //重构图
{
for(int e = first[u]; e != -1; e = edge[e].next)
{
int v = edge[e].v;
if(belong[u] != belong[v])
{
ind[belong[v]]++;
read_graph2(belong[u], belong[v]);
}
}
}
if(toposort()) printf("Yes\n");
else printf("No\n");
}

int main()
{
int T;
scanf("%d", &T);
while(T--)
{
init();
scanf("%d%d", &n, &m);
while(m--)
{
int u, v;
scanf("%d%d", &u, &v);
read_graph(u, v);
}
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: