其他分享
首页 > 其他分享> > codeforces 771 (VK Cup 2017 - Round 1)

codeforces 771 (VK Cup 2017 - Round 1)

作者:互联网

传送门

A. Bear and Friendship Condition

•题意

给你n个人,m个朋友关系

朋友是会传递的,若A B是朋友,A C是朋友,则必须有B C的朋友关系

符合这个关系输出YES,否则输出NO

•思路

n个人,但凡是有朋友关系的,必定在同一个朋友圈内

所以可以分成若干个朋友圈

在一个朋友圈内部,若符合条件肯定是互为朋友

也就是 是一个完全图

接下来就是判断是否是完全图了

举个栗子:1234在一个朋友圈内,且符合条件

则人与朋友的对应关系为

1与1 2 3 4为朋友

2与1 2 3 4为朋友

3与1 2 3 4为朋友

4与1 2 3 4为朋友

即,他们的朋友是完全相同的!

挨个去判断朋友是否相同显然时间复杂度不够优雅

只需要排序后,看第一个朋友是否相等就可以

O(n)变O(1)!

为什么呢? 因为每个人的朋友圈都要去查看一遍,如果A的朋友圈没有B,但是B的朋友圈有A

那么,B和A的朋友圈肯定对不上,所以就输出NO了

•代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int maxn=2e5+5;
 5 vector<int> a[maxn];
 6 //我加vis数组是为了减少不必要的查看来减少时间
 7 //氮素 貌似效率还不如不加vis的,搞不懂 ???
 8 bool vis[maxn];
 9 
10 int main()
11 {
12 //    freopen("C:\\Users\\14685\\Desktop\\C++workspace\\in&out\\contest","r",stdin);
13     int n,m;
14     cin>>n>>m;
15     for(int i=1;i<=m;i++)
16     {
17         int x,y;
18         cin>>x>>y;
19         a[x].push_back(y);
20         a[y].push_back(x);
21     }
22     ///把自己也加进自己的朋友圈
23     for(int i=1;i<=n;i++)
24         a[i].push_back(i);
25     ///排序
26     for(int i=1;i<=n;i++)
27         sort(a[i].begin(),a[i].end());
28 
29     ///查看每个人的朋友圈
30     for(int i=1;i<=n;i++)
31     {
32         if(vis[i])
33             continue;
34         ///自己的朋友圈和朋友的朋友圈对比
35         for(int j=0;j<a[i].size();j++)
36         {
37             if(a[i].size()==a[a[i][j]].size())
38             {
39                 vis[a[i][j]]=true;
40                 ///朋友圈不相同
41                 if(a[i][0]!=a[a[i][j]][0])
42                 {
43                     puts("NO");
44                     return 0;
45                 }
46             }
47             else
48             {
49                  puts("NO");
50                  return 0;
51             }
52         }
53     }
54     puts("YES");
55 }
View Code

 

B - Bear and Different Names

•题意

有n个人,从1个人开始每k个一组

[1,k] [2,k+1]....

如果有重名的则NO,否则YES

根据NO和YES的结果输出名字

名字首字母大写,且1<=名字长度<=10

•思路

因为名字长度有限制,可能有很多人名字不同

所以首先预处理出不同名字来,注意计算名字个数

(这里踩了坑)

首先找到第一个YES为切入点,后边的名字可以由他得到

已经确定了的名字不能再更改!否则会引起与前面的YES/NO不符 (这里也踩了坑

如果是YES的话就选择新名字,否则选择和这k个人的第一个人相同的名字(也就是首尾名字重合

然后再找第一个YES前面的人,从第一个YES开始倒找,让他前面的都和他重名

•代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int maxn=2e5+5;
 5 string name[55],nname[3000];
 6 string s[55];
 7 int wh[10];
 8 ///预处理名字
 9 void Init()
10 {
11     for(int i=0;i < 10;++i)
12         wh[i]=i;
13     int cnt=0;
14     do
15     {
16         for(int i=0;i<10;i++)
17         {
18             if(i==0)
19                 nname[++cnt]=wh[0]+'A';
20             else
21                 nname[cnt]+=(wh[i]+'a');
22         }
23         if(cnt>2500)
24             return ;
25     }while(next_permutation(wh,wh+10));
26 }
27 int main()
28 {
29 //    freopen("C:\\Users\\14685\\Desktop\\C++workspace\\in&out\\contest","r",stdin);
30     int n,m;
31     cin>>n>>m;
32     bool flag=false;
33     Init();
34     int cut=0;
35     for(int i=1;i<=n-m+1;i++)
36     {
37         cin>>s[i];
38         if(s[i]=="YES")
39         {
40             flag=true;
41             for(int j=i;j<=i+m-1;j++)
42                 if(name[j].empty())
43                     name[j]=nname[++cut];///选择新名字
44         }
45         else///这k个人首尾名字重合
46             name[i+m-1]=name[i];
47     }
48 
49     if(!flag)
50         for(int i=1;i<=n;i++)
51             cout<<"Aa"<<' ';
52     else
53     {
54         ///找第一个YES
55         int index;
56         for(index=1;index<=n-m+1;index++)
57             if(s[index]=="YES")
58                 break;
59         ///前面的人和他重名
60         for(int i=index;i>=0;i--)
61             name[i]=name[index];
62 
63         for(int i=1;i<=n;i++)
64             cout<<name[i]<<' ';
65     }
66 }
View Code

 

标签:771,Cup,int,VK,朋友,名字,朋友圈,NO,YES
来源: https://www.cnblogs.com/MMMinoz/p/11561321.html