7-15 球队“食物链” (30 分)

某国的足球联赛中有N支参赛球队,编号从1至N。联赛采用主客场双循环赛制,参赛球队两两之间在双方主场各赛一场。

联赛战罢,结果已经尘埃落定。此时,联赛主席突发奇想,希望从中找出一条包含所有球队的“食物链”,来说明联赛的精彩程度。“食物链”为一个1至N的排列{ T1​​ T2​​ ⋯ TN​​ },满足:球队T1​​战胜过球队T2​​,球队T2​​战胜过球队T3​​,⋯,球队T(N1)​​战胜过球队TN​​,球队TN​​战胜过球队T1​​。

现在主席请你从联赛结果中找出“食物链”。若存在多条“食物链”,请找出字典序最小的。

注:排列{ a1​​ a2​​ ⋯ aN​​}在字典序上小于排列{ b1​​ b2​​⋯ bN​​ },当且仅当存在整数K(1KN),满足:aK​​<bK​​且对于任意小于K的正整数i,ai​​=bi​​。

输入格式:

输入第一行给出一个整数N(2N20),为参赛球队数。随后N行,每行N个字符,给出了N×N的联赛结果表,其中第i行第j列的字符为球队i在主场对阵球队j的比赛结果:W表示球队i战胜球队j,L表示球队i负于球队j,D表示两队打平,-表示无效(当i=j时)。输入中无多余空格。

输出格式:

按题目要求找到“食物链”T1​​ T2​​ ⋯ TN​​,将这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"

题意:输出一条包含所有队伍且去重的最小字典序的球队T(N1)​​战胜过球队TN​​,球队TN​​战胜过球队T1的集合,输入时'W'表示i(行)队赢了j(列)队,'L'表示j(列)队赢了i(行)队,若找的到则输出,否则输出“No Solution”。

注意:1,
此题要求“食物链”包含所有球队,因此此链长度为n。

          2,此题要求“食物链”输出字典序最小的,而搜索按升序搜索,因此只需输出第一个即可满足最小字典序的条件
          3,判断下一步是否能走,若不能则返回,若不加这步会超时
          4,标记用一维数组是因为每支队伍在链中有且只有出现一次
          5,注意这里可能要建立双向边
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int amn=1e2+5;
 6 int a[amn][amn],mp[amn],ans[amn];
 7 char in[amn];
 8 int n,f=0;
 9 void s(int i,int len)
10 {
11     if(f)return;
12     ans[len]=i;
13     if(len==n)///此题要求“食物链”包含所有球队,因此此链长度为n
14     {
15         if(a[i][1])///此题要求“食物链”输出字典序最小的,而搜索按升序搜索,因此只需输出第一个即可满足最小字典序的条件
16             f=1;
17         return;
18     }
19     ///判断下一步是否能走,若不能则返回,若不加这步会超时
20     int cn=0;
21     for(int p=1; p<=n; p++)
22     {
23         if(mp[p]==0&&a[p][1]==1)
24             cn=1;
25     }
26     if(cn==0) return;
27     for(int k=1; k<=n; k++)
28     {
29         ///如果当前存在下一步且下一步能走,则继续搜索
30         if(a[i][k]==1&&mp[k]==0)mp[i]=1,s(k,len+1),mp[i]=0;///标记当前节点,回溯后清除标记,标记用一维数组是因为每支队伍在链中有且只有出现一次
31     }
32 }
33 int main()
34 {
35 
36     while(cin>>n)
37     {
38         memset(a,0,sizeof(a));
39         for(int i=1; i<=n; i++)
40         {
41             ans[i]=amn;
42             mp[i]=0;
43             scanf("%s",in+1);
44             for(int j=1; j<=n; j++)
45             {
46                 if(in[j]=='W')a[i][j]=1;///注意这里可能要建立双向边
47                 if(in[j]=='L')a[j][i]=1;
48             }
49         }
50         f=0;
51         s(1,1);
52         if(f)
53         {
54             for(int i=1; i<=n; i++)
55             {
56                 cout<<ans[i];
57                 if(i<n)cout<<" ";
58                 else cout<<endl;
59             }
60         }
61         else
62         {
63             cout<<"No Solution
";
64         }
65 
66     }
67 }
 
原文地址:https://www.cnblogs.com/Railgun000/p/10526135.html