UVA1670/Gym-100085K Kingdom Roadmap 思维+dfs

这道题看起来似乎并不难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;
}

猜你喜欢

转载自blog.csdn.net/Cc_Sonia/article/details/81988037