Data structures | disjoint-set entry template title --HDU1232

EDITORIAL:

Speaking in front of the entry and search sets , and now let's look at a specific topic, and thought to write the code, and to deepen the understanding of the investigation set.

HDU1232-- Smooth Traffic Project

Problem Description

A provincial survey of urban traffic, urban roads to get existing tables, the table lists the cities and towns each road directly connected. Target provincial government "Smooth Traffic Project" is to make the province between any two towns can implement traffic (but not necessarily directly connected to the road, as long as you can reach each other indirectly through road). Minimum asked how many roads also need to build?

Input

Test input contains several test cases. Each test case is given row of the first two positive integers, are the number of towns N (<1000) and road number M; M rows corresponding to the next M path, each row is given a pair of positive integers, respectively, the number two towns in direct communication path. For simplicity, the town numbered from 1 to N.
Note: number of roads may be communicated between the two cities, ie
. 3. 3
. 1 2
. 1 2
2. 1
This input is valid
when N is 0, an input end, the use cases are not processed.

Output

For each test case, the number of roads in at least one line in the output needed construction.

Sample Input

4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0

Sample Output

1
0
2
998

Hint

Huge input, scanf is recommended.

Source

Zhejiang University computer graduate re-examination on test - 2005

Topic links: http://acm.hdu.edu.cn/showproblem.php?pid=1232

Reference Code:

1. [disjoint-set - compression path, are consolidated rank]

// 31MS 1384K 864 B G++ 【路径压缩,按秩合并】
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int n,m;
int t1,t2;
int parent[1005];// 树型结构的根节点 
int r[1005];// 秩 

//【并查集中的<查>】 
// 路径压缩 
int find_parent(int p)
{
    if(parent[p]!=p)parent[p]=find_parent(parent[p]);
    return parent[p];   
}

//【并查集中的<并>】 
// 按秩合并 
void unite(int x,int y)
{
    int root_x=find_parent(x);
    int root_y=find_parent(y);
    if(root_x==root_y)return;
    if(r[root_x]>r[root_y])parent[root_y]=root_x;
    else
    {
        parent[root_x]=root_y;
        if(r[root_x]==r[root_y])r[root_y]++;
    }
}

// 计算有多少个联通分量 
int get_ans(int num)
{
    int sum=0;
    for(int i=1;i<=num;i++)
    {
        if(parent[i]==i)sum++;
    }
    return sum;
}

int main()
{
    while(~scanf("%d",&n) && n)
    {
        for(int i=1;i<=n;i++)
        {
            parent[i]=i;
            r[i]=0;
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&t1,&t2);
            unite(t1,t2);
        }
        printf("%d\n",get_ans(n)-1); // 最后结果需要减1
                                     // (这个应该比较好理解,例如有n个点,只需要n-1条线段就能将它们连起来) 
    }
}

2. [disjoint-set - path compression]

// 31MS 1388K 853 B G++ 【按秩合并】
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int n,m;
int t1,t2;
int parent[1005];
int r[1005];

int find_parent(int p)
{
    if(parent[p]==p)return p;
    return find_parent(parent[p]);   
}

void unite(int x,int y)
{
    int root_x=find_parent(x);
    int root_y=find_parent(y);
    if(root_x==root_y)return;
    if(r[root_x]>r[root_y])parent[root_y]=root_x;
    else
    {
        parent[root_x]=root_y;
        if(r[root_x]==r[root_y])r[root_y]++;
    }
}

int get_ans(int num)
{
    int sum=0;
    for(int i=1;i<=num;i++)
    {
        if(parent[i]==i)sum++;
    }
    return sum;
}

int main()
{
    while(~scanf("%d",&n) && n)
    {
        for(int i=1;i<=n;i++)
        {
            parent[i]=i;
            r[i]=0;
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&t1,&t2);
            unite(t1,t2);
        }
        printf("%d\n",get_ans(n)-1); 
    }
}

3. [simple disjoint-set]

// 15MS 1384K 725B G++ 【朴素并查集】
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int n,m;
int t1,t2;
int parent[1005];

int find_parent(int p)
{
    if(parent[p]==p)return p;
    return find_parent(parent[p]);  
}

void unite(int x,int y)
{
    int root_x=find_parent(x);
    int root_y=find_parent(y);
    if(root_x==root_y)return;
    else parent[root_y]=root_x;
}

int get_ans(int num)
{
    int sum=0;
    for(int i=1;i<=num;i++)
    {
        if(parent[i]==i)sum++;
    }
    return sum;
}

int main()
{
    while(~scanf("%d",&n) && n)
    {
        for(int i=1;i<=n;i++)
        {
            parent[i]=i;
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&t1,&t2);
            unite(t1,t2);
        }
        printf("%d\n",get_ans(n)-1); 
    }
}

Written in the last:

Template title above is a disjoint-set, in fact, seeking a graph, the number of China Unicom components.

What Unicom components are? Here posted a blog , you can point to look into.(Good lazy, do not want to write your own)

Guess you like

Origin blog.csdn.net/weixin_33757911/article/details/90806486