Codeforce Round #544(Div3)

F1:

  给一个无向图,求它的一棵生成树,使得生成树度数最大的点的度数尽可能大

  题解:

  找到度数最大的点,把与这个点相连的所有边加入,然后遍历一遍所有的边,建一棵生成树就好了

  错误想法:把边排序,使得两端点度数最大值大的边在前面,这样前面的边就是度数最大的了(并不)

  原因:如果度数最大的点有两个或者更多,就会有这种情况:

  假设 a,b两点度数最大且相同,那么排序的时候,a,b都在前面,但是a不一定在b前面,同样,b也不一定在a前面,这就会造成:a用了一般,b用了一半,但是此时已经构成了一棵生成树,但是这棵树的度数最大的点显然小于degree[a]=degree[b]

  (upd:其实这么做也可以,排序的时候加个下面这种东西:

  

1 bool cmp(pii a,pii b)
2 {
3     if(max(deg[a.first],deg[a.second]) == max(deg[b.first],deg[b.second])) return min(a.first,a.second) <min(b.first,b.second);
4     return max(deg[a.first],deg[a.second]) > max(deg[b.first],deg[b.second]);
5 }

  不加第三行会出现上述错误,添加后可AC)(不过这也....太丑了)

  代码如下:

  

 1 #include<bits/stdc++.h>
 2 #define pii pair<int,int>
 3 using namespace std;
 4 const int maxn=2e5+5;
 5 vector<int> G[maxn];
 6 int parent[maxn];
 7 int deg[maxn];
 8 int n,m;
 9 int find(int x)
10 {
11     return x==parent[x]?x:parent[x]=find(parent[x]);
12 }
13 int main()
14 {
15     ios::sync_with_stdio(0);
16     cin>>n>>m;
17     for(int i=1;i<=n;++i) parent[i]=i;
18     for(int i=1;i<=m;++i)
19     {
20         int a,b; cin>>a>>b;
21         ++deg[a],++deg[b];
22         G[a].push_back(b);
23         G[b].push_back(a);
24     }
25     int sta,maxx=0;
26     for(int i=1;i<=n;++i)
27     {
28         if(deg[i]>=maxx) sta=i,maxx=deg[i];
29     }
30     int cnt=0;
31     for(int i=0;i<G[sta].size();++i)
32     {
33         ++cnt;
34         int to=G[sta][i];
35         parent[to]=sta;
36         printf("%d %d\n",sta,to);
37     }
38     for(int i=1;i<=n;++i)
39     {
40         if(i==sta) continue;
41         for(int j=0;j<G[i].size();++j)
42         {
43             if(cnt==n-1) break;
44             int to=G[i][j];
45             int a=find(i),b=find(to);
46             if(a==b) continue;
47             else
48             {
49                 ++cnt;
50                 parent[b]=a;
51                 printf("%d %d\n",i,to);
52             }
53         }
54     }
55 }

 

posted @ 2019-04-09 21:48  codeoos  阅读(110)  评论(0编辑  收藏  举报