您的位置:首页 > 编程语言 > C语言/C++

POJ 2762 强连通分量中存在单相连通边 【tarjan+toposort+缩点】.cpp

2012-10-03 21:33 344 查看
[b]题意:[/b]

[b]  给出一些房间之间的关系[/b]

  问任意两个房间是否存在一条互通的路径..即单相连通..

  输入:

  给出T表示有T组数据

  每组数据给出n m 表示n个房间 m个关系

  接下来m行..每行给出a b 表示a房间 和 b房间之间是连通的..

  如果任意两个房间之间存在单相连通..则输出yes 否则 no

[b]思路:[/b]

[b]  先用tarjan算法求出每个强连通分量..然后对每一个进行染色..[/b]

  然后建图..拓扑排序..

  如果排序不唯一..就是有超过两个点是有0个初度的..

  这代表其中有两个房间是不相连的..



[b]Tips:[/b]

[b]  点太多或者边太多的情况下..[/b]

  就要用前向星建图了..

[b]Code:[/b]

View Code

#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define clr(x) memset(x, 0, sizeof(x))
const int INF = 0x1f1f1f1f;
const int MAXN = 1010;

int n, m;

struct Edge
{
int to;
int next;
}edge[1000010], edge2[1000010];
int head[MAXN], head2[MAXN];
int tot, tot2;

void add(int s, int u)
{
edge[tot].to = u;
edge[tot].next = head[s];
head[s] = tot++;
}

void add2(int s, int u)
{
edge2[tot2].to = u;
edge2[tot2].next = head2[s];
head2[s] = tot2++;
}

int ti, top, cnt;
int dfn[MAXN], low[MAXN], ins[MAXN];
int col[MAXN], sta[MAXN];

void tarjan(int u)
{
int i, k;
dfn[u] = low[u] = ++ti;
sta[++top] = u;
ins[u] = 1;
for(i = head[u]; i != -1; i = edge[i].next) {
k = edge[i].to;
if(dfn[k] == 0) {
tarjan(k);
low[u] = min(low[u], low[k]);
}
else if(ins[k]) {
low[u] = min(low[u], dfn[k]);
}
}

if(dfn[u] == low[u]) {
++cnt;
do
{
k = sta[top--];
col[k] = cnt;
ins[k] = 0;
}while(k != u);
}
}

void solve_ta()
{
ti = top = cnt = 0;
clr(dfn), clr(ins);
for(int i = 1; i <= n; ++i)
if(!dfn[i])
tarjan(i);
}

int ind[MAXN];
int q[MAXN];
int v[MAXN];
int f1, f2, num;

void make_G()
{
int i, j, k;
tot2 = 0;
memset(head2, 0xff, sizeof(head2));

solve_ta();
for(i = 1; i <= n; ++i)
for(j = head[i]; j != -1; j = edge[j].next) {
k = edge[j].to;
if(col[i] != col[k]) {
add2(col[i], col[k]);
ind[col[k]]++;
}
}
}

void toposort()
{
int front = 0, rear = 0;
int i, k;
f1 = 1, f2 = 0;
clr(ind);
make_G();

for(i = 1; i <= cnt; i++)
if(ind[i] == 0)
q[rear++] = i;
if(rear > 1)
f1 = -1;
num = 0;
while(front < rear) {
int x = q[front++];
int tt = 0;
num++;
for(i = head2[x]; i!=-1; i = edge2[i].next) {
k = edge2[i].to;
ind[k]--;
if(ind[k] == 0) {
q[rear++] = k;
tt++;
}
}
if(tt > 1)
f2 = -1;
}
}
int main()
{
int i, j, k;
int T;
int a, b;
bool flag;
while(scanf("%d", &T) != EOF)
while(T--)
{
tot = 0;
memset(head, 0xff, sizeof(head));
flag = true;

scanf("%d %d", &n, &m);
while(m--) {
scanf("%d %d", &a, &b);
add(a, b);
}

toposort();
if(f1 == -1 || f2 == -1 || num != cnt) flag = false;

if(flag) puts("Yes");
else puts("No");
}
return 0;
}




[b]题目链接:http://poj.org/problem?id=2762[/b]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐