CodeForces 25D(并查集)

来源:互联网 发布:婚礼录像编辑软件 编辑:程序博客网 时间:2024/06/06 19:20

Description

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.

Input

The first line contains integer n (2 ≤ n ≤ 1000) — amount of cities in Berland and neighboring countries. Next n - 1 lines contain the description of roads. Each road is described by two space-separated integers aibi (1 ≤ ai, bi ≤ n, ai ≠ bi) — pair of cities, which the road connects. It can't be more than one road between a pair of cities. No road connects the city with itself.

Output

Output the answer, number t — what is the least amount of days needed to rebuild roads so that from each city it became possible to reach all the others. Then output t lines — the plan of closure of old roads and building of new ones. Each line should describe one day in the format i j u v — it means that road between cities i and j became closed and a new road between cities u and v is built. Cities are numbered from 1. If the answer is not unique, output any.

Sample Input

Input
21 2
Output
0
Input
71 22 33 14 55 66 7
Output
13 1 3 7

【题意】有N座城市,之间有n-1条路(双向),现在要使所有城市连通(不一定直达,中间可以有若干转折点),操作是删掉一条路,同时重修一条路,求用最少操作使所有城市连通,并写出要拆的路径和要重建的路径。

【分析】刚开始也没看懂,以为很复杂,到后来看了别人的博客后才知道这是个并查集问题,这也是我第一次接触并查集的题,可能代码不是很完美,望各位大神指点。

        其实就是先把各个城市先当成独立的集合,其中的元素只有它本身,然后每加进来一条路,就把它所两头的集合合并,代表着这些城市都来连通了,比如{1,2,3},{6,7,8}是已知的连通的城市集合,假如现在又加进来一条连通路2—6,那么这两个集合尽可以合并了,{1,2,3,6,7,8},这就是一个新集合,代表里面任意两个城市都是连通的,所以路径更新完后只需要遍历所有的集合,集合数num-1就是要新建的路(拆的和建的一样多)。

【参考】点击打开链接

   还有一个并查集详解:http://http://blog.csdn.net/dellaserss/article/details/7724401/

详见代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int N=10005;int n;int str[N];struct tree{    int x,y;}p[N];int finds(int x){    if(x==str[x])        return x;    else        return finds(str[x]);}int main(){    int a,b;    while(~scanf("%d",&n))    {        int ans=0;        for(int i=1;i<=n;i++)            str[i]=i;        for(int i=1;i<n;i++)        {            scanf("%d%d",&a,&b);            int aa=finds(a);            int bb=finds(b);            if(aa==bb)            {                p[ans].x=a;                p[ans].y=b;                ans++;            }            if(aa<bb)            {                str[bb]=aa;            }            else                str[aa]=bb;        }        int num=0;        int g[N];        for(int i=1;i<=n;i++)            if(str[i]==i)             g[num++]=i;        printf("%d\n",num-1);        int i=0;        while(1)        {            if(i>=num-1)                break;            printf("%d %d %d ",p[i].x,p[i].y,g[i]);            i++;            printf("%d\n",g[i]);        }    }    return 0;}