现在的位置: 首页 > 综合 > 正文

poj 3713 Transferring Sylla 判断无向图是否每两个点之间都能至少有3点不同的路径可达 是否3-连通

2013年02月04日 ⁄ 综合 ⁄ 共 3092字 ⁄ 字号 评论关闭

After recapturing Sylla, the Company plans to establish a new secure system, a transferring net! The new system is designed as follows:

The Company staff choose N cities around the nation which are connected by "security tunnels" directly or indirectly. Once a week, Sylla is to be transferred to another city through the tunnels. As General ordered, the transferring net must reach a certain security level that there are at least 3 independent paths between any pair of cities a, b. When General says the paths are independent, he means that the paths share only a and b in common.

Given a design of a transferring net, your work is to inspect whether it reaches such security level.

Input

The input consists of several test cases.
For each test case, the first line contains two integers, N ≤ 500 and M ≤ 20000. indicating the number of cities and tunnels.
The following M lines each contains two integers a and b (0 ≤ a, b < N), indicating the city a and city b are connected directly by a tunnel.

The input ends by two zeroes.

Output

For each test case output "YES" if it reaches such security level, "NO" otherwise.

Sample Input

4 6
0 1
0 2
0 3
1 2
1 3
2 3

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

7 6
0 1
0 2
0 3
1 2
1 3
2 3

0 0
Sample Output

YES
NO
NO

 

 

 

 

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=550;
//给出一个无向图(可能不联通),判断是否每两个点之间都能至少有3点不同的路径可达,
//即该图是否至少是3-连通图,即至少去掉3个点图才不联通
//枚举删去一个点,看是否还存在割点,如果存在割点,则不是3连通图
//tarjan算法求无向连通图的割点个数
struct edge
{
 int t,w;
 int next;
};
int V,E;//顶点个数 边数
int p[maxn];
edge G[42000];
int l;
void init()
{
 memset(p,-1,sizeof(p));
 l=0;
}
void addedge(int u,int t,int w,int l)
{
 G[l].w=w;
 G[l].t=t;
 G[l].next=p[u];
 p[u]=l;
}
int del;
//tarjan 求割点 割边
int cut[maxn];//cut[i]非0表示i是割点
int color[maxn];//颜色:0表示没有访问,1表示正在访问,2表示访问结束
int lowc[maxn];//表示i及i的子孙相连的辈分最高的祖先节点所在的深度
int d[maxn];//表示i节点在树中的深度
int root;//根节点
int fath;//父节点
int pcnt;//割点个数
int egcnt;//割边个数
int flag;//是否存在割点 1:有  0:没有
void dfs(int u,int fath,int deep)
{
    if(flag) return ;
    color[u]=1;//正在访问
    lowc[u]=d[u]=deep;//深度
    int tot=0;//子树个数
    for(int i=p[u];i!=-1;i=G[i].next)
    {
        int t=G[i].t;
        if(t!=fath&&color[t]==1)
        {
            lowc[u]=min(lowc[u],d[t]);
        }
        if(color[t]==0)
        {
            dfs(t,u,deep+1);
            tot++;//子树加1
            lowc[u]=min(lowc[u],lowc[t]);
            //求割点
            if((u==root&&tot>1)||(u!=root&&lowc[t]>=d[u])) cut[u]=1,flag=1;//不能将pscnt++写到这里
            //求割边
            //if(lowc[t]>d[u]) edge[u][t]=true;  u->t是割边
        }
    }
    color[u]=2;
}
void calc()
{
    pcnt=egcnt=0;
    memset(cut,0,sizeof(cut));
    memset(color,0,sizeof(color));color[del]=2;
    memset(lowc,0,sizeof(lowc));
    memset(d,0,sizeof(d));
    root=1;
    if(del==1) root=2;
    dfs(root,-1,1);
    //for(int i=1;i<=V;i++) if(cut[i]) pcnt++;
}
int main()
{
 while(scanf("%d%d",&V,&E)==2)
    {
        if(V==0&&E==0) break;
     init();//初始化
        for(int i=0;i<E;i++)
        {
            int u,t,w=1;
            scanf("%d%d",&u,&t);u++,t++;
            addedge(u,t,w,l++);
            addedge(t,u,w,l++);
        }
        flag=0;
        for(int i=1;i<=V;i++)
        {
            del=i;
            calc();//求割点
            for(int j=1;j<=V;j++)
            {
                if(color[j]==0)
                {
                    flag=1;
                    break;
                }
            }
            if(flag) break;
        }
        if(flag) printf("NO\n");
        else printf("YES\n");
 }
 return 0;
}

 

 

抱歉!评论已关闭.