题意:
某国的足球联赛中有N支参赛球队,编号从1至N。联赛采用主客场双循环赛制,参赛球队两两之间在双方主场各赛一场。
联赛战罢,结果已经尘埃落定。此时,联赛主席突发奇想,希望从中找出一条包含所有球队的“食物链”,来说明联赛的精彩程度。“食物链”为一个1至N的排列{ T1 T2 ... TN },满足:球队T1战胜过球队T2,球队T2战胜过球队T3,……,球队T(N-1)战胜过球队TN,球队TN战胜过球队T1。
现在主席请你从联赛结果中找出“食物链”。若存在多条“食物链”,请找出字典序最小的。
注:排列{ a1 a2 ...aN }在字典序上小于排列{ b1 b2 ... bN },当且仅当存在整数K(1 <= K <= N),满足:aK < bK且对于任意小于K的正整数i,ai=bi。
输入格式:
输入第一行给出一个整数N(2 <= N <= 20),为参赛球队数。随后N行,每行N个字符,给出了NxN的联赛结果表,其中第i行第j列的字符为球队i在主场对阵球队j的比赛结果:“W”表示球队i战胜球队j,“L”表示球队i负于球队j,“D”表示两队打平,“-”表示无效(当i=j时)。输入中无多余空格。
输出格式:
按题目要求找到“食物链”T1 T2 ... TN,将这N个数依次输出在一行上,数字间以1个空格分隔,行的首尾不得有多余空格。若不存在“食物链”,输出“No Solution”。
分析:
1、若能形成食物链,字典序最小的一定以1开头。所以从1开始搜。
2、剪枝:若剩下没选的点,都不能战胜球队1,则剪掉。
3、给出的联赛结果表不是对称的,即“W”表示球队i战胜球队j,“L”表示球队i负于球队j这两个都需要标记。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define lowbit(x) (x & (-x))
const double eps = 1e-8;
inline int dcmp(double a, double b){
if(fabs(a - b) < eps) return 0;
return a > b ? 1 : -1;
}
typedef long long LL;
typedef unsigned long long ULL;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const int MOD = 1e9 + 7;
const double pi = acos(-1.0);
const int MAXN = 20 + 10;
const int MAXT = 10000 + 10;
using namespace std;
char pic[MAXN][MAXN];
int a[MAXN][MAXN];
bool vis[MAXN];
int ans[MAXN];
int N;
bool ok;
void dfs(int cur, int now){
if(ok) return;
ans[now] = cur;
if(now == N){
if(a[cur][1]){
ok = true;
}
return;
}
bool flag = false;
for(int i = 1; i <= N; ++i){
if(!vis[i] && a[i][1]){
flag = true;
break;
}
}
if(!flag) return;
for(int i = 1; i <= N; ++i){
if(!vis[i] && a[cur][i]){
vis[i] = true;
dfs(i, now + 1);
if(ok) return;
vis[i] = false;
}
}
}
int main(){
scanf("%d", &N);
for(int i = 1; i <= N; ++i){
scanf("%s", pic[i] + 1);
}
for(int i = 1; i <= N; ++i){
for(int j = 1; j <= N; ++j){
if(pic[i][j] == 'W'){
a[i][j] = 1;
}
else if(pic[i][j] == 'L'){
a[j][i] = 1;
}
}
}
vis[1] = true;
dfs(1, 1);
if(!ok){
printf("No Solution\n");
return 0;
}
for(int i = 1; i <= N; ++i){
if(i != 1) printf(" ");
printf("%d", ans[i]);
}
printf("\n");
return 0;
}