2020牛客暑期多校训练营(第二场)C Cover the Tree

————————————————————————————————————————————————————————————
今天的签到题就是手速题,除了签到最简单就是这道的(虽然过的人不多,但是真的简单)。
emmm手推+大胆猜测得出dfs序(其实比赛的时候没有意识到是dfs序,但是不碍事),后来发现1-2-3,这种奇怪的连法,想到1不一定能作为根节点。
然后一直wa 90%到自闭。后来发现奇数的时候,最后输出连到根节点的锅。虽然我感觉好像没什么问题……
看了一下别人的代码,有很多大佬有一个getroot函数,大概是求根节点的?太辣鸡了没看懂,但是感觉好像随便找一个边>1的点就ok了(反正我过了)
还有一种没有求dfs序的,直接按顺序统计,很多大佬说是假算法,数据太弱才过的。但是,我感觉dfs序排出来和顺序好像是一样的吖……反正我比赛的时候是这么觉得的。太辣鸡了,没有仔细想,以后想懂了可能会回来改吧。
都说了是大胆猜测了,肯定是不会证明的……把官方题解放上来吧。

#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <stack> #include <queue> #include <map> #include <vector> #include <set> #include <deque> #include <cfloat> #include <algorithm> typedef long long ll; using namespace std; int gcd(int x,int y) { return y?gcd(y,x%y):x; } int lcm(int x,int y) { return x/gcd(x,y)*y; } int n,m,mod; vector<int> t[1001000]; vector<int> l; bool vis[1001000]; int num,dfsn; void dfs(int x) { dfsn++; if(t[x].size()==1) { l.push_back(x); return; } else { vis[x]=true; for(int i=0;i<t[x].size();i++) { int v=t[x][i]; if(!vis[v]) { dfs(v); } } vis[x]=false; } } int main() { int n; scanf("%d",&n); for(int i=0;i<n-1;i++) { int x,y; scanf("%d%d",&x,&y); t[x].push_back(y); t[y].push_back(x); } if(n==1) { printf("0\n"); return 0; } else if(n==2) { printf("1\n"); printf("1 2\n"); return 0; } else { int x; for(x=1;x<=n;x++) { if(t[x].size()>1) { dfs(x); break; } } int sum=l.size(); printf("%d\n",(sum+1)/2); for(int i=0;i<sum/2;i++) { printf("%d %d\n",l[i],l[sum/2+i]); } if(sum%2) { printf("%d %d\n",l[0],l[sum-1]); } } }

浙公网安备 33010602011771号