题意:
n支队伍打淘汰赛,每轮都是两两配对,胜者进入下一轮。
每支队伍的实力固定,并且已知每两支队伍间的比赛结果(不可能为平局,则一定有一方打败另一方),你喜欢一号队,但是一号队不一定是最强的,但是他可以直接打败其他队伍中的至少一半,并且对于每支一号队不能打败的队伍t,总是存在一支1号队能直接打败的队伍t’ 使得t’ 能直接打败t,输出比赛安排。先输出最底层的,比如n = 8 先输出 8场第一轮比赛 4场第二轮比赛 2 场第三轮比赛 1场第四轮比赛。
分析:
条件1: 一号队总能打败其他队伍中至少一半
条件2: 总存在被1号队打败的队伍打败1号队不能打败的队伍
只要保持这个条件总存在,就可以递归。
step1: 选出一号队可以打败的队伍t’ 使得t’ 可以打败t 但是一号队打不败t
这一步之后 t’ 会全部赢 t
step2: 选出一支1号队可以打败的队伍,与之对战
step3: 对于1号队不能打败的队伍,两两自相残杀
这一步之后 一号队不能打败的队伍减半
step4: 剩余队伍的自由匹配
这一轮下来,t’ 大获全胜, 而且对于1号队打不掉的队伍,总在t’中,这样条件2成立
对于条件1, 由于step1 和step3 总能保证t 至少去掉了一半
不过如果t只有1个的话, step1一定有t’ 将t击败,因此由这两步可以确认至少去掉一半的打不过的队伍。
细心的朋友可能发现了
step2 一定可以进行吗
显然是可以的, 由于 step1 一定是 t’ 和 t的匹配,假设全部匹配成功了,至少还存在 1个队伍 和一号队 还没匹配,根据条件一,step2总成立。
代码:
#include<bits/stdc++.h>
#define LL long long
#define ms(s) memset(s, 0, sizeof(s))
using namespace std;
const int maxn = 1024 + 10;
char G[maxn][maxn];
int vis[maxn], haveFailed[maxn];
int n;
void dfs(int m) {
if(m == 1) return;
ms(vis);
//step 1
for(int i = 2; i <= n; i++) {
for(int j = 2; j <= n