Codeforces Round #346 (Div. 2)

A - Round House

题意:长度为n个环、起始位置是a,然后给出b,b是正数代表顺时针跑b个单位、b是负数代表逆时针跑b个单位、

思路:基础数学题目吧、

PS:对于C++和G++编译器而言 比如-7%3的结果是-1、但在数学中是2、 这题所要的结果是在数学中的、

 1 #include<cmath>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 using namespace std;
 6 int main()
 7 {
 8     int n,a,b;
 9     scanf("%d%d%d",&n,&a,&b);
10         int ans=(a+b)%n;
11         if(ans<=0)    ans+=n;
12         printf("%d\n",ans);
13     return 0;
14 }
View Code

B - Qualifying Contest

题意:就说一个国家要举办区域赛、有m个地区、每个地区至少有两只得分不同的队伍,一共有n个队伍参赛,求出每个地区(从1地区输出到m地区)选出两个队伍出来、要求这两个队伍在他所属的地区中排名前两位、排名按得分来排、如果一个地区有多种选择那么就输出‘?’,否则输出选出的两只队伍、

思路:先按地区排序然后地区相同按得分来排、然后一个地区一个地区的扫、对于每个地区能选出队伍的情况就两种、一种是当前地区的最高分恰好只有两个、另外一种是最高分一个第二高分一个、 其他情况均不符合、在扫的时候记录一下最高分和次高分的位置就可以了、

 1 #include<cmath>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 struct Team
 8 {
 9     string name;
10     int id;
11     int score;
12     string reve;
13     bool operator < (Team a)
14     {
15         if(id==a.id)    return score>a.score;
16         return id<a.id;
17     }
18 }team[100005];
19 string chong[100005];
20 int n,m;
21 int main()
22 {
23     cin >> n >> m;
24     for(int i=0;i<n;++i){
25         cin >> team[i].name >> team[i].id >> team[i].score;    
26         for(int i=0;i<team[i].name.size();++i)
27             team[i].reve+=tolower(team[i].name[i]);
28     }
29     int k=0;
30     sort(team,team+n);
31     for(int i=0;i<n;++i){
32         int a,b,qa,qb,j,sa,sb;    // a b用来记录当前地区最高分和次高分、 
33         qa=qb=0;        // qa qb 用来记录最高分和次高分出现的次数、 
34         a=b=-1;         // sa sb 记录的是最高分和次高分第一次出现的位置、 
35         for(j=i;j<n;++j){
36             if(team[j].id!=team[i].id)    break;    //不属于当前地区的话就退出循环、 
37             if(a==-1)    a=team[j].score,sa=j,qa=1;
38             else if(a==team[j].score)    qa++;
39             else if(b==-1)    b=team[j].score,sb=j,qb=1;
40             else if(b==team[j].score)    qb++;
41         }
42         if(qa==2)
43             cout << team[sa].name << " " << team[sa+1].name << endl;
44         else if(qa==1&&qb==1)
45             cout << team[sa].name << " " << team[sb].name << endl;
46         else     cout << "?" << endl;
47         i+=(j-i-1);    //分界点要注意一下、 
48     }
49     return 0;
50 }
View Code

PS:这题我自己踩到自己的坑了、 就是在a,b赋值的时候我是直接为0并且在寻找最高分和次高分的时候判断是否等于0、等于0就代表当前没有最高分和最高分、

如果有两个队伍分数恰好为0、那我判断就与我设想的不一样了、 所以被WA在51组数据、提醒一下自己把、 在设置判断变量的时候一定要设置为不可能的值、

C - Tanya and Toys

题意:给出n个物品每个物品有一个数值、每个不一样的数值代表一种类型的物品、现在给出一个容量m、要你求出最多能买多少类型不同的物品、举个样例吧、

3 7

1 3 4  输出是2 5 就是说买下物品2的话容量还剩下 7 - 2 = 5、 但是 3 和 4又存在、 所以直接向后枚举咯、

思路:用map记录已经存在的物品、然后从1枚举到m(基于贪心的思想,因为要求最多还能买下多少物品)、 如果物品不存在就购买、然后容量减少、

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<map>
 6 using namespace std;
 7 int n,m,x;
 8 int num[100005];
 9 int main()
10 {
11     map<int,int>q;
12     scanf("%d%d",&n,&m);
13     for(int i=0;i<n;++i){
14         scanf("%d",&x);
15         q[x]++;
16     }
17         
18     sort(num,num+n);
19     int sum=0;
20     int ans=m;
21     for(int i=1;i<=ans;++i){
22         if(q[i]>0)    continue;
23         if(m-i<0)    break;
24         num[sum++]=i;
25         m-=i;
26     }
27     printf("%d\n",sum);
28     for(int i=0;i<sum;++i)
29         if(i==0)    printf("%d",num[i]);
30         else        printf(" %d",num[i]);
31     printf("\n");
32     return 0;
33 }
View Code

 

E - New Reform

题意:给出一个图、原来是无向图、现在要你改成有向图、是入度为0的点尽可能小、并输出入度为0的点的个数、

思路:想通了其实就是想办法判环、 如果是环那么整个环的贡献就是0、否则每一个连通块的贡献就是1

我这里写了一个dfs判环的思路、感觉不是很好呀、

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<iostream>
 5 #define mst(ss,b) memset(ss,b,sizeof(ss))
 6 using namespace std;
 7 const int qq=200100;    //要注意一下数据范围、因为是开的无向图、 
 8 int n,m;
 9 int head[qq],vis[qq],top;
10 struct Edge{
11     int v,next;
12 }edge[qq];
13 void init()
14 {
15     mst(head,-1);
16     top=0;
17     mst(vis,0);
18 }
19 void Add(int u,int v)
20 {
21     edge[top].v=v;
22     edge[top].next=head[u];
23     head[u]=top++;
24 }
25 int ans=0,flag;
26 void dfs(int u,int pre)
27 {
28     for(int i=head[u];i!=-1;i=edge[i].next){
29         int v=edge[i].v;
30         if(v==pre)    continue;
31         if(!vis[v]){
32             vis[v]=1;
33             dfs(v,u);
34         }
35         else    flag=1;    //如果已经访问到了已经访问过的点、那么就有环了 
36     }
37 }
38 void solve()
39 {
40     for(int i=1;i<=n;++i){
41         flag=0;
42         if(!vis[i]){
43             vis[i]=1;
44             dfs(i,0);
45             if(flag==0)    ans++;
46         }
47     }
48     cout << ans << endl;
49 }
50 int main()
51 {
52     init();
53     scanf("%d%d",&n,&m);
54     for(int i=1;i<=m;++i){
55         int u,v;
56         scanf("%d%d",&u,&v);
57         Add(u,v);
58         Add(v,u);
59     }
60     solve();
61     return 0;
62 }
View Code

在codeforces上找了一个大牛的代码、也差不多是dfs但是判断环的条件和我这个不一样、感觉很好理解阿

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n,m,x,y,vis[100005],re,edg,co;
 5 vector< vector<int> > adj;
 6 
 7 void dfs(int u){
 8 vis[u]=1;co++;
 9 for(int j=0;j<adj[u].size();j++){
10     int v=adj[u][j];edg++;
11     if(!vis[v]) dfs(v);
12 }
13 }
14 
15 int main(){
16 cin>>n>>m;re=0;
17 adj.assign(n,vector<int>(0));
18 for(int i=0;i<m;i++){
19     cin>>x>>y;
20     x--;y--;
21     adj[x].push_back(y);adj[y].push_back(x);
22 }
23 for(int i=0;i<n;i++){
24     if(!vis[i]){
25         edg=co=0;dfs(i);
26         edg/=2;
27         if(edg==co-1) re++;
28     }
29 }
30 cout<<re<<endl;
31 return 0;
32 }
View Code

 

posted @ 2016-05-20 11:29  我不萌、我要高冷  阅读(223)  评论(0编辑  收藏  举报