公平竞赛

给定n个队伍和m场比赛,目标是找到显示比赛公平的队伍组合,使得比赛结果形成一个公平的环。要求找到最小的k值及对应的队伍序列。输入描述包括队伍数量、比赛数量和各场比赛详情,输出k值和队伍序列。示例展示了如何从无向图中寻找最小环。解题思路涉及将有向图转化为二分图并使用BFS寻找环。
摘要由CSDN通过智能技术生成

题目描述

有n个队伍打了m场比赛。如果存在一些队伍,a1,a2,…,ak使得a1赢过了a2,a2赢过a3,…,ak赢过a1,就显得比赛很不公平,且k越大越不公平。反过来说,
如果这些队伍满足a1赢过a2,a2输过a3,a3赢过a4,…,ak输过a1,那比赛就显得很公平,且k越小越公平。具体的说,我们希望找到a1,a2,…,ak这k支队伍(可以重复),并且存在m1,m2,…,mk这k场比赛(比赛不能重复)(为了方便令m0也表示mk,a0也表示ak),使得对于所有的0≤i≤k-1,mi在ai和ai+1之间进行,且对于所有的0≤i≤k-1,比赛mi(m0即为mk)和mi+1的结果对于ai+1是相同的(结果相同意味着ai+1输了这两场比赛或者赢了这两场比赛)。现在给出若干场比赛,试选出这k支队伍(可以重复)以显得比赛很公平,或者判
定这样的k不存在。k存在的情况下,还要尽量小(有些数据不要求k尽量小)。

输入描述:

输入的第一行包含0或者1。1意味着后面每组数据只要正确判断能否找到满足条件的k个队伍并在能找出时输出这k个队伍即为正确,不需要最小化k。0意味着必须最小化k才算正确。接下来有至多6组数据(共享6秒时限)。第一行两个正整数n和m表示队伍的数量比赛的数量(1≤n≤5000,1≤m≤min(1000000,n⋅(n−1)))。接下来每行两个正整数a和b表示队伍a战胜了队伍b(1≤a,b≤n)。 保证一个队伍不会战胜另一个队伍两次。但是两个队伍可能互相战胜过。为了方便,输入的最后有一行单独的0。

输出描述:

第一行输出一个整数k(1≤k≤1000000)表示选出的队伍的数量,这个数量应该尽可能的小(除了某些测试点)。如果无法选出则在第一行输出−1且不需要输出第二行。 第二行输出k个整数a1,…,ak表示题目要求的k个队伍(可以重复)。

示例1

输入

0
6 8
1 2
3 2
3 6
1 6
2 5
3 5
4 6
4 1
0

输出

4
1 6 3 2

说明

输出的环可以从任意位置开始,顺时针逆时针均可。如
4
6 1 2 3

4
6 3 2 1
也算正确。

备注:

对于30%的数据,只要正确判断能否找到并在可以找到时输出k个满足条件的队伍即可得分,不需要让k尽量小。对于另外30%的数据,有
1≤n≤1000。

思路

本题给定了一个有向图,要求找出一个环,其中可以有重点但是不能有重边, 且环上的边方向是交错的。
我们可以把每个点拆成两个点a赢和a输,分别表示这个点在环上是作为赢两 次的点出现或者输两次的点出现。那么一场比赛a赢了b,就相当于从a赢连 到b输的一条边,或者从b输连到a赢的一条边。原来的一个环可以对应到拆 点以后的一个环。
现在我们得到了一个二分图,而且是无向的。无向图找最小环可以用bfs解决。 暴力可以得100分,即从每个点开始找到最小环就break(可以证明如果一个 无向图的平均度数至少是8,那么它一定包含一个环。所以bfs时只要搜索最 多5000*8条边,一定会找到环并break。)。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=5050,M=1e6+500;
int gti(void)
{
    
    char c=getchar();
    int ret=0,st=1;
    for (;!isdigit(c);c=getchar()) if (c=='-') st=-1;
    for (;isdigit(c
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值