【ZSTU4213 2015年12月浙理工校赛 D】【双连通分量tarjan算法】One-Way Roads 无向连通图确定边的方向使得全图任意两点间可达

4213: One-Way Roads

Time Limit: 1 Sec   Memory Limit: 128 MB   Special Judge
Submit: 133   Solved: 45

Description

In the ACM kingdom, there are N cities connected by M two-way roads. These cities are connected, i.e., one can reach from any city X to any other city Y by going through some of these roads. One day, the government wishes to assign for each road a direction, such that one can still reach from any city to any other. You are asked to determine whether this task is possible.

Input

The first line of input contains T(0 ≤ T ≤ 100), the number of test cases. The first line of each test case consists of two integers, N(1 ≤ N ≤ 50), and M(1 ≤ M ≤ N(N − 1)/2). Each of the next M lines describes a road, and consists of two integers, X and Y, (1 ≤ X, Y ≤ N; X ≠ Y), indicating that there is a road between city X and Y. There is at most one road that directly connects each pair of cities.

Output

For each test case, if it is impossible, output a single line NO. Otherwise, output YES on the first line, followed by M lines describing one possible direction assignment to these M roads. Each of these M lines should consist of two integers, X, Y, indicating that there is a one-way road from city X to city Y. These Mlines can be output in any order.

Sample Input

3
3 3
1 2
2 3
1 3
4 3
1 2
1 3
1 4
4 5
1 2
2 3
4 3
1 4
2 4

Sample Output

YES
1 2
2 3
3 1
NO
YES
1 2
2 3
3 4
4 1
2 4

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}
template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}
const int N=60,M=3600,Z=1e9+7,ms63=0x3f3f3f3f;
int casenum,casei;
int n,m,x,y;
int id,tim,top,color,g;
int first[N],s[N],low[N],dfn[N];bool e[N];
int w[M],nxt[M];pair<int,int>ans[M];
void ins(int x,int y)
{
    ++id;
    w[id]=y;
    nxt[id]=first[x];
    first[x]=id;
}
void tarjan(int x,int lastz)
{
    low[x]=dfn[x]=++tim;
    s[++top]=x;e[x]=1;
    for(int z=first[x];z;z=nxt[z])
    {
		if((z^lastz)==1)continue;
        int y=w[z];
        if(dfn[y]==0)
		{
			ans[++g]=make_pair(x,y);
			tarjan(y,z);
		}
        if(e[y])
		{
			if(dfn[y]<dfn[x])ans[++g]=make_pair(x,y);
			gmin(low[x],low[y]);
		}
    }
    if(dfn[x]==low[x])
    {
        if(++color>1)return;
        while(1)
        {
            int y=s[top--];
            e[y]=0;
            if(y==x)break;
        }
    }
    return;
}
int main()
{
    scanf("%d",&casenum);
    for(casei=1;casei<=casenum;++casei)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
        {
            dfn[i]=low[i]=0;
            first[i]=0;
            e[i]=0;
        }
        id=1;
        for(int i=1;i<=m;++i)
        {
            scanf("%d%d",&x,&y);
            ins(x,y);
            ins(y,x);
        }
		tim=top=color=g=0;
		tarjan(1,0);
        if(color==1)
        {
            puts("YES");
            for(int i=1;i<=g;++i)printf("%d %d\n",ans[i].first,ans[i].second);
        }
		else puts("NO");
    }
    return 0;
}
/*
【题意】
比赛的时候要是有spj,这道题就1A了,这场比赛是大概能够AK的。唉= = 

给你一个联通无向图,让你使得每一条边有向化,
问你可否在这个基础上,使得图上的任意两点间都存在一条可达路径。

【类型】
双连通分量

【分析】
这题只要判定图中是否存在一个极大(包含图上所有点)双连通分量即可。
于是我们直接套上可以解决双连通分量的tarjan算法。

从父节点连向子节点的边,我们不再次处理(否则就出错了),
其他所有边的方向,只要顺着dfs的方向连就好啦!
然后看看是否双连通分量只有一个。如果是,输出YES和具体的连边方案就好啦。

注意,一条边只能连一次。
我们是可能从一个时间戳较大的点,走到一个时间戳较小的点的。
而这条边也恰恰需要从这个时间戳较大的点,指向时间戳较小的点。
然而,这是深搜,我们可能后来还会走回那个时间戳较小的点,这时要注意,不要再把边的连向搞反了。

换句话说,我们连边的原则是——
1,连向一个新的点时,方向是指向新的点的。
2,放弃返祖边。
3,两个点都不是新点时,方向是指向旧的点(时间戳小的点)。

【时间复杂度&&优化】
O(n)

*/


你可能感兴趣的:(构造,图论-双联通分量)