zzulioj-1676与同学比身高(并查集)

Posted LesRoad

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了zzulioj-1676与同学比身高(并查集)相关的知识,希望对你有一定的参考价值。

题目链接: http://acm.zzuli.edu.cn/problem.php?id=1676

 

题目描述

新学年开学了,学校又迎来了一批新同学,已知部分同学之间的身高关系,请列出可推断出的同学之间的身高关系。

输入

第一行是一个整数n,表示有n组测试数据。
每组测试数据第一行是一个正整数m(m<=100),表示已知同学之间的身高关系有m组,身高关系没有相等的情况。
接下来输入m行身高关系,每位同学用一个大写字母表示。

输出

对于第d组测试数据,首先输出“Case d:”,d从1开始。
输出能够推断出的同学之间的身高关系,按字母的字典序输出。
已知条件中的身高关系不要输出。
如果推断不出任何新的身高关系,输出NONE。

样例输入

2
3
A<B
C>B
C<D
2
A<B
C<D

样例输出

Case 1:
A<C
A<D
B<D
Case 2:
NONE

解法1:DFS

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 bool vis[30][30];
 4 int m;
 5 vector<int>V[30];
 6 struct node
 7 {
 8     int a, b;
 9 } q[1004];
10 bool cmp(node x, node y)
11 {
12     if(x.a == y.a) return x.b < y.b;
13     return x.a < y.a;
14 }
15 void dfs(int x, int y)
16 {
17     for(int i = 0; i < V[y].size(); i++)
18     {
19         int v = V[y][i];
20         if(!vis[x][v])
21         {
22             q[++m].a = x;
23             q[m].b = v;
24         }
25         dfs(x, v);
26     }
27 }
28 int main()
29 {
30     int t, n, i;
31     cin>>t;
32     int cas = 0;
33     while(t--)
34     {
35         scanf("%d", &n);
36         for(i = 0; i < 26; i++) V[i].clear();
37         memset(vis, 0, sizeof vis);
38         m = 0;
39         while(n--)
40         {
41             char s[5];
42             scanf("%s", s);
43             int a = s[0] - A;
44             int b = s[2] - A;
45             if(s[1] == <) V[a].push_back(b), vis[a][b] = 1;
46             else V[b].push_back(a), vis[b][a] = 1;
47         }
48         printf("Case %d:\n", ++cas);
49         for(i = 0; i < 26; i++)
50             dfs(i, i);
51         sort(q+1, q+1+m, cmp);
52         for(i = 1; i <= m; i++)
53             printf("%c<%c\n", q[i].a+A, q[i].b+A);
54         if(!m) puts("NONE");
55     }
56     return 0;
57 }

 

解法2:BFS

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 bool vis[30][30];
 4 int m;
 5 vector<int>V[30];
 6 struct node
 7 {
 8     int a, b;
 9 } q[1004];
10 bool cmp(node x, node y)
11 {
12     if(x.a == y.a) return x.b < y.b;
13     return x.a < y.a;
14 }
15 int main()
16 {
17     int t, n, i;
18     cin>>t;
19     int cas = 0;
20     while(t--)
21     {
22         scanf("%d", &n);
23         for(i = 0; i < 26; i++) V[i].clear();
24         memset(vis, 0, sizeof vis);
25         m = 0;
26         while(n--)
27         {
28             char s[5];
29             scanf("%s", s);
30             int a = s[0] - A;
31             int b = s[2] - A;
32             if(s[1] == <) V[a].push_back(b), vis[a][b] = 1;
33             else V[b].push_back(a), vis[b][a] = 1;
34         }
35         printf("Case %d:\n", ++cas);
36         for(i = 0; i < 26; i++)
37         {
38             queue<int>Q;
39             Q.push(i);
40             while(!Q.empty())
41             {
42                 int t = Q.front();
43                 Q.pop();
44                 for(int j = 0; j < V[t].size(); j++)
45                 {
46                     int v = V[t][j];
47                     if(!vis[i][v])
48                     {
49                         q[++m].a = i;
50                         q[m].b = v;
51                     }
52                     Q.push(v);
53                 }
54             }
55         }
56         sort(q+1, q+1+m, cmp);
57         for(i = 1; i <= m; i++)
58             printf("%c<%c\n", q[i].a+A, q[i].b+A);
59         if(!m) puts("NONE");
60     }
61     return 0;
62 }

 

解法3:并查集

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int vis[30][30], par[30];
 4 int main()
 5 {
 6     int n, m, i, j;
 7     char s[5];
 8     cin>>n;
 9     int cas = 0;
10     while(n--)
11     {
12         scanf("%d", &m);
13         for(i = 0; i < 26; i++) par[i] = i;
14         memset(vis, 0, sizeof vis);
15         while(m--)
16         {
17             scanf("%s", s);
18             int a = s[0] - A;
19             int b = s[2] - A;
20             if(s[1] == <)
21                 par[a] = b, vis[a][b] = 1;
22             else
23                 par[b] = a, vis[b][a] = 1;
24         }
25         printf("Case %d:\n", ++cas);
26         m = 0;
27         for(i = 0; i < 26; i++)
28         {
29             for(j = 0; j < 26; j++)
30             {
31                 int k = i;
32                 if(i == j) continue;
33                 while(1)
34                 {
35                     k = par[k];
36                     if(k == j && !vis[i][j])
37                     {
38                         printf("%c<%c\n", i+A, j+A);
39                         m++;
40                     }
41                     if(k == par[k]) break;
42                 }
43             }
44         }
45         if(!m) puts("NONE");
46     }
47     return 0;
48 }

 解法4:floyd


 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int mp[30][30];
 4 int main()
 5 {
 6     int t, n;
 7     cin>>t;
 8     int cas = 0;
 9     while(t--)
10     {
11         scanf("%d", &n);
12         memset(mp, 0, sizeof mp);
13         bool f = false;
14         while(n--)
15         {
16             char s[5];
17             scanf("%s", s);
18             int a = s[0] - A;
19             int b = s[2] - A;
20             if(s[1] == <) mp[a][b] = 1;
21             else mp[b][a] = 1;
22         }
23         printf("Case %d:\n", ++cas);
24         for(int k = 0; k < 26; k++)
25             for(int i = 0; i < 26; i++)
26                 for(int j = 0; j < 26; j++)
27                     if(mp[i][k] && mp[k][j] && !mp[i][j])
28                         mp[i][j] = 2, f = true;
29         for(int i = 0; i < 26; i++)
30             for(int j = 0; j < 26; j++)
31                 if(mp[i][j] == 2)
32                     printf("%c<%c\n", i+A, j+A);
33         if(!f) puts("NONE");
34     }
35     return 0;
36 } 

以上是关于zzulioj-1676与同学比身高(并查集)的主要内容,如果未能解决你的问题,请参考以下文章

关于并查集的一切全在这里了

分数调查(带权并查集)

HihoCoder - 1515 分数调查 (带权并查集)

[Offer收割]编程练习赛15 B.分数调查[加权并查集]

[luogu P2170] 选学霸(并查集+dp)

poj2524(并查集水题)