问题 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

样例输出

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值