给你一群队伍,1号对至少能击败一半的队伍,每只一号队不能击败的队伍都有另一只队伍能击败他。给一个比赛安排让一号队夺冠(黑幕!)
n=2时,一号队必能击败对手夺冠。所以我们的目标就是在满足题目条件的情况下不断减少队伍,最后n=2一号队夺冠。
四个阶段:尽量配对打不过的,给1号队挑一个能打败的,把剩下黑色队伍任意配对,剩下所有队伍任意配对,然后递归。
因为过程是一个log2 n 所以用n>>1正好;
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
int beat[1100][1100];
vector<int>::iterator i1,i2;
int main()
{
int n;
while(cin>>n)
{
char s[1100];
vector<int>Left;
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
for(int j=1;j<=n;j++)
beat[i][j]=s[j]-'0';
}
for(int i=2;i<=n;i++)
Left.push_back(i);
while(n>1)
{
n>>=1;
vector<int>Left1,Left2,fin,win,lose;
for(int i=0;i<Left.size();i++)
if(beat[1][Left[i]]) win.push_back(Left[i]);
else lose.push_back(Left[i]);
for(int i=0;i<lose.size();i++)
{
int b=0;
for(int j=0;j<win.size();j++)
if(win[j]>0&&beat[win[j]][lose[i]])
{
printf("%d %d\n",win[j],lose[i]);
b=1;
fin.push_back(win[j]);
win[j]=-1;
break;
}
if(!b) Left1.push_back(lose[i]);
}
for(int i=0;i<win.size();i++)
{
if(win[i]>0)
{
printf("1 %d\n",win[i]);
win[i]=-1;
break;
}
}
for(int i=0;i+1<Left1.size();i+=2)
{
printf("%d %d\n",Left1[i],Left1[i+1]);
if(beat[Left1[i]][Left1[i+1]]) fin.push_back(Left1[i]);
else fin.push_back(Left1[i+1]);
}
if(Left1.size()%2)
Left2.push_back(Left1[Left1.size()-1]);
for(int i=0;i<win.size();i++)
if(win[i]>0) Left2.push_back(win[i]);
for(int i=0;i+1<Left2.size();i+=2)
{
printf("%d %d\n",Left2[i],Left2[i+1]);
if(beat[Left2[i]][Left2[i+1]]) fin.push_back(Left2[i]);
else fin.push_back(Left2[i+1]);
}
Left=fin;
}
}
return 0;
}