这道题看起来似乎并不难emmmmm...
一开始想的是找度为1的点,互相连边,结果WA了。。后来发现可能有">-<"这种结构,这样很可能左边两点、右边两点互相连,但如果切断中间那条边,图就不连通了,很明显错误的。。
后来听某大佬说,要用dfs搜一遍度为1的点(叶子节点)并标号(相同父亲的节点标号连续);然后从中间分开,前一半和后一半相连。中间有一些细节就不多说了,在代码里体现了。
附上AC代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
typedef pair<int,int>pp;
#define pb push_back
const double pi=acos(-1.0);
const double eps=1e-9;
const int INF=0x3f3f3f3f;
const ll MOD=1e9+7ll;
const int MAX=100005;
vector<int>edge[MAX];
bool vis[MAX];
int leaf[MAX],cnt;
void dfs(int u)
{
if(edge[u].size()==1)//注意是=1而不是=0!
{
leaf[cnt++]=u;
//return; //注意不能return!
}
for(int i=0;i<edge[u].size();i++)
{
int v=edge[u][i];
if(!vis[v])
{
vis[v]=true;
dfs(v);
}
}
}
int main()
{
freopen("kingdom.in","r",stdin);
freopen("kingdom.out","w",stdout);
int n;
while(scanf("%d",&n)==1)
{
if(n==2)
{
printf("1\n");
printf("1 2\n");
continue;
}
for(int i=0;i<=n;i++)
edge[i].clear();
int u,v;
for(int i=0;i<n-1;i++)
{
scanf("%d%d",&u,&v);
edge[u].pb(v);
edge[v].pb(u);//注意无向图连两次边
}
cnt=0;
memset(vis,false,sizeof(vis));
vis[1]=true;
dfs(1);
if(cnt%2)
leaf[cnt++]=leaf[cnt/2];
int mid=(cnt+1)/2;//注意+1
printf("%d\n",mid);
for(int i=0,j=mid;i<mid&&j<cnt;i++,j++)//从中间分开连边匹配
{
printf("%d %d\n",leaf[i],leaf[j]);
}
}
return 0;
}