codeforce 25D

 Roads not only in Berland

题目描述:

Berland Government decided to improve relations with neighboring countries. First of all, it was decided to build new roads so that from each city of Berland and neighboring countries it became possible to reach all the others. There are n cities in Berland and neighboring countries in total and exactly n - 1 two-way roads. Because of the recent financial crisis, the Berland Government is strongly pressed for money, so to build a new road it has to close some of the existing ones. Every day it is possible to close one existing road and immediately build a new one. Your task is to determine how many days would be needed to rebuild roads so that from each city it became possible to reach all the others, and to draw a plan of closure of old roads and building of new ones.

题意大概就是有N个点和N-1条边,你需要每次删掉一条边然后加上一条边,直到使这个图连通。

输入N代表N个点,然后输入N-1条边,先输出你的操作次数,然后依次输出你删掉的边和你要加的边。操作方式可能有多种输出任意一个符合题目要求的即可。
样例:

input:

2

1 2

output:

0

input:

7

1 2

2 3

3 1

4 5

5 6

6 7

output:

1

3 1 3 7

并查集的简单应用,每次输入一条边就检验是否在同一集合内,如果已经在同一集合内,就记录下来表示要删掉,如果不在,就维护一下并查集即可,最后找到还没有进入这个集合的点,和集合内的任意一点连接就行了。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<stack>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXM=10001;

int par[MAXM];
int sub1[MAXM];
int sub2[MAXM];
int pls1[MAXM];
int pls2[MAXM];
int n;

void init(int n)
{
    for (int i=1;i<=n;i++)
    {
        par[i]=i;
    }
}
int find(int x)
{
    if (par[x]==x)
        return x;
    return par[x]=find(par[x]);
}
bool same(int x,int y)
{
    return find(x)==find(y);
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        init(n);
        memset(sub1,0,sizeof(sub1));
        memset(sub2,0,sizeof(sub2));
        memset(pls1,0,sizeof(pls1));
        memset(pls2,0,sizeof(pls2));
        int tot=1;
        for (int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if (same(x,y))
            {
                sub1[tot]=x;
                sub2[tot]=y;
                tot++;
            }
            else
                par[find(y)]=find(x);
        }
        int now=find(1);
        int cnt=1;
        for (int i=2;i<=n;i++)
        {
            if (find(i)!=now)
            {
                pls1[cnt]=i;
                pls2[cnt]=1;
                cnt++;
                par[find(i)]=now;
            }
        }
       printf("%d\n",cnt-1);
        for (int i=1;i<cnt;i++)
            printf("%d %d %d %d\n",sub1[i],sub2[i],pls1[i],pls2[i]);
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值