第十四届浙江财经大学程序设计竞赛 J-Journey

链接: https://www.nowcoder.com/acm/contest/89/J
来源:牛客网

题目描述

Mr.Frog wants to travel all over the country, and as we all know the country consists of N cities and M directed roads connecting these cities. The cities are numbered from 1 to N. The roads are numbered from 1 to M, the ith road connects the city Ui to Vi which means Mr.Frog can move to city Vi from city Ui.

Mr.Frog wants to travel all cities, and he can choose a city to start his trip casually and choose a city to end his trip casually. In order to avoid the boredom in the journey, Mr.Frog decides to make a plan that can help him arrive each city exactly once and pass through each road exactly once. Now give you the information of the cities and roads. Please tell Mr.Frog whether there exists a way that can satisfy his plan.

输入描述:

 
 

The first line contains an integer T, where T is the number of test cases. T test cases follow. For each test case, the first line contains two integers N and M, where N is the number of cities, and M is the number of roads.

Then next M lines follow, the ith line contains two integers Ui and Vi, indicating there is a directed road from city Ui to city Vi.

• 1 ≤ T ≤ 105. • 1 ≤ N ≤ 105. • 0 ≤ M ≤ 105. • 1 ≤ Ui,Vi ≤ N. • the sum of N in all test cases doesn’t exceed 106.• the sum of M in all test cases doesn’t exceed 106.

输出描述:

For each test case, print a line containing “Case #x:”, where x is the test case number (starting from 1).

In the next line, print the city number in the order of his journey, if there is a way that can satisfy his plan; otherwise print “NO”.

题解:
欧拉通路,据题意,不可以生成环。
只有一个点入度为0,一个点出度为0才可以,其他点出度,入度必须都为1,
但是这样还是可能出现一个欧拉通路加一个环的情况,加一个并查集判断一下。
代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
using namespace std;
const int maxn=1e5+7;
int in[maxn],out[maxn],la[maxn],par[maxn];
queue<int>P;
int find(int x)
{
    if(x==par[x])return x;
    return par[x]=find(par[x]);
}
void unite(int x,int y)
{
    x=find(x);y=find(y);
    if(x!=y)par[x]=y;
}
int main()
{
    int T,cas=0;scanf("%d",&T);
    while(T--)
    {
        int n,m;scanf("%d%d",&n,&m);
        for(int i=0;i<=n;i++)
        {
            in[i]=out[i]=0;
            par[i]=i;
        }
        if(m==0)//m==0的情况要特判一下
        {
            printf("Case #%d:\n",++cas);
            if(n==1)printf("1\n");
            else printf("NO\n");
            continue;
        }
        while(m--)
        {
            int x,y;scanf("%d%d",&x,&y);
            out[x]++;in[y]++;
            la[x]=y;
            unite(x,y);
        }
        int r1=0,r2=0,id1,id2;bool bb=0;
        for(int i=1;i<=n;i++)
        {
            if(out[i]==0)r1++,id2=i;
            if(in[i]==0)r2++,id1=i;
            if(out[i]>1||in[i]>1)bb=1;
            if(out[i]==0&&in[i]==0)bb=1;
        }
        for(int i=2;i<=n;i++)
            if(find(1)!=find(i))bb=1;
        printf("Case #%d:\n",++cas);
        if(!bb&&r1==1&&r2==1)
        {
            while(id1!=id2)
            {
                printf("%d ",id1);
                id1=la[id1];
            }
            printf("%d\n",id2);
        }
        else printf("NO\n");
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值