某国的足球联赛中有N支参赛球队,编号从1至N。联赛采用主客场双循环赛制,参赛球队两两之间在双方主场各赛一场。
联赛战罢,结果已经尘埃落定。此时,联赛主席突发奇想,希望从中找出一条包含所有球队的“食物链”,来说明联赛的精彩程度。“食物链”为一个1至N的排列{ T
1
T
2
⋯ T
N
},满足:球队T
1
战胜过球队T
2
,球队T
2
战胜过球队T
3
,⋯,球队T
(N−1)
战胜过球队T
N
,球队T
N
战胜过球队T
1
。
现在主席请你从联赛结果中找出“食物链”。若存在多条“食物链”,请找出字典序最小的。
注:排列{ a1 a
2
⋯ a
N
}在字典序上小于排列{ b
1
b
2
⋯ b
N
},当且仅当存在整数K(1≤K≤N),满足:a
K
<b
K
且对于任意小于K的正整数i,a
i
=b
i
。
输入格式:
输入第一行给出一个整数N(2≤N≤20),为参赛球队数。随后N行,每行N个字符,给出了N×N的联赛结果表,其中第i行第j列的字符为球队i在主场对阵球队j的比赛结果:W表示球队i战胜球队j,L表示球队i负于球队j,D表示两队打平,-表示无效(当i=j时)。输入中无多余空格。
输出格式:
按题目要求找到“食物链”T
1
T
2
⋯ T
N
,将这N个数依次输出在一行上,数字间以1个空格分隔,行的首尾不得有多余空格。若不存在“食物链”,输出“No Solution”。
输入样例1:
5
-LWDW
W-LDW
WW-LW
DWW-W
DDLW-
输出样例1:
1 3 5 4 2
输入样例2:
5
-WDDW
D-DWL
DD-DW
DDW-D
DDDD-
输出样例2:
No Solution
总结
剪枝时不要想着一蹴而就,可以从开头或结尾某个好判断的点进行入手, 本题就是从存不存在可以当结尾走到起点的点了
使用printf("%d%c", a, " \n"[i==n])来输出可以方便结尾有空格的情况
对于dfs记录路径,可以开一个数组记录路径,要用到,参数传值,不需要pre数组
#include <iostream>
#include <stack>
#include <cstring>
#include <vector>
using namespace std;
const int N = 30;
int g[30][30];
int pre[30];
bool st[30];
int n;
vector<int> v[N];
bool dfs1(int u, int lev, int s)
{
bool x = true;
for (int i = 1; i <= n; i++) {
if (!st[i] && g[i][1] == 1) x = false;
}
if (x) return false;
st[u] = true;
for (int i = 0; i < v[u].size(); i++) {
int j = v[u][i];
if (lev == n && s == j) {
pre[s] = u;
return true;
}else {
if (!st[j]) {
pre[j] = u;
if (dfs1(j, lev + 1, s)) return true;
}
}
}
st[u] = false;
return false;
}
int main()
{
memset(h, -1, sizeof h);
cin >> n;
string s;
for (int i = 1; i <= n; i++) {
cin >> s;
for (int j = 0; j < n; j++) {
if (s[j] == 'W') g[i][j + 1] = 1;
else if (s[j] == 'L') g[j + 1][i] = 1;
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (g[i][j]) v[i].push_back(j);
}
}
for (int i = 1; i <= n; i++) {
if (g[i][1]) {
judge[i] = true;
cont++;
}
}
bool flag = true;
for (int i = 1; i <= n; i++) {
memset(st, false, sizeof st);
if (dfs1(i, 1, i)) {
flag = false;
stack<int> k;
int f = pre[i];
while (f != i) {
k.push(f);
f = pre[f];
}
k.push(i);
bool check = false;
while (!k.empty()) {
if (!check) {
cout << k.top();
check = true;
}else cout << " " << k.top();
k.pop();
}
break;
}
}
if (flag) cout << "No Solution" << endl;
return 0;
}