问题 G: Cycles

题目描述

The ACM kingdom has n ≥ 2 cities, numbered from 1 to n , and m (bidirectional) roads.
Each road connects two distinct cities. For all i,j ∈ {1,2, … , n}, there is at most one road connecting cities i and j. We want to know whether both conditions below hold:
·The ACM kingdom is connected. That is, city i is reachable from city j via a finite number of roads for all i,j ∈ {1,2, … , n}.
·The ACM kingdom has at least two distinct cycles. Here a cycle starts at a city, goes through a positive number of roads and finally ends at the starting city. Except for the starting city,
no city can appear twice on a cycle. Furthermore, two cycles are said to be distinct as long as their sets of roads are not exactly the same.
If the two conditions above hold, we would like to further know whether the ACM kingdom has at least three distinct cycles.

输入

The first line is the number of test cases. The first two lines of each test case are n and m, in that order. Then each of the m roads is specified by the two cities (separated by a space) that it connects.

输出

Each test case requires the following output: If it is not true that the ACM kingdom is connected and has at least two distinct cycles, output “n” in a line. Otherwise, output “y” in a line if the ACM kingdom has exactly two distinct cycles and “y: there are at least three cycles” in a line if the ACM kingdom has at least three distinct cycles.

样例输入

样例数据

3
9
10
1 2
1 3
3 5
5 6
5 7
7 3
2 4
9 4
4 8
2 8
6
7
4 3
4 5
4 6
1 4
2 4
3 5
5 6
3
2
1 2
3 2

样例输出

扫描二维码关注公众号,回复: 8614525 查看本文章
y
y: there are at least three cycles
n

提示

·There are at most 15 test cases.
·2 ≤n≤ 9.

根据题目意思,首先声明代码来自超哥~,做了略微修改,深感大佬的码力深厚。

简单理一下思路;

从第一个点开始深度优先遍历,dfs函数有两个参数,第一个当前点,另外一个是这个点的前驱节点,

因为存图的时候存的是无向图,可能会从当前节点回到前驱节点,故特判一下,此外每遍历到一个新的节点,时间戳+1,

因为最后要用时间戳这个变量判断图的连通性,当dfs的时候遍历到一个点的时间戳不为零且比当前节点的时间戳小的时候那么就是存在环了,此时需要将环上的每一条边的权值加+1,通过记录的前驱节点去操作,这么做的目的是判断有没有存在一条边存在于两个环,即当一条边的权值为2的时候那么这条边就存在于两个环中了。

上代码吧!

#include<bits/stdc++.h>
using namespace std;
const int maxn=100+10;
int n,m,k,ans,ans2,tim,pre[maxn],num[maxn],head[maxn];  // pre数组为遍历过程中当前节点的前驱节点  num为时间戳 
struct edge 
{ 
	int before; 
	int to;
	int w;
}e[maxn<<2];
void add(int u,int v,int w=0) 
{
    e[k].to=v; 
	e[k].w=w;
    e[k].before=head[u]; 
	head[u]=k++;
}
void init()
{
	tim=0;k=0;ans=0;ans2=0; 
	memset(head,-1,sizeof head);
	memset(num,0,sizeof num);
	memset(pre,0,sizeof pre); 
}
void targan(int u,int f) 
{
    num[u]=++tim; 
    for (int i=head[u];i!=-1;i=e[i].before) 
	{
        int v=e[i].to;  
        if(v==f) 
		continue;
        else if(num[v]) 
		{
            if(num[v]<num[u]) 
			{ 
                ans++;
                e[i].w++;  
                ans2=max(ans2,e[i].w+e[i^1].w);
                int idx=u;  
                while(idx!=v) 
				{
                    e[pre[idx]].w++; 
                    ans2=max(ans2,e[pre[idx]].w+e[pre[idx]^1].w);
                    idx=e[pre[idx]^1].to;          
                } 
            }
            continue;
        }
        pre[v]=i;
        targan(v,u);
    } 
}  
int main() 
{ 
    int T; 
    scanf("%d",&T);
    for (int t=1;t<=T;t++) 
	{
        scanf("%d %d",&n,&m);
        init();
        for (int i=1;i<=m;i++) 
		{
            int x,y;
            scanf("%d %d",&x,&y);
            add(x,y);
            add(y,x);  
        }
        targan(1,0);
        if (tim!=n) 
		printf("n\n");
        else if(ans>=3||ans2>=2) 
		{
            printf("y: there are at least three cycles\n");
        }
        else if (ans==2) 
		{
            printf("y\n");
        }
        else printf("n\n");
    }
    return 0;
}
发布了51 篇原创文章 · 获赞 21 · 访问量 3094

猜你喜欢

转载自blog.csdn.net/qq_44115065/article/details/101543387