UPC-6492 Connectivity(并查集&联通块计数&哈希)

题目描述
There are N cities. There are also K roads and L railways, extending between the cities. The i-th road bidirectionally connects the pi-th and qi-th cities, and the i-th railway bidirectionally connects the ri-th and si-th cities. No two roads connect the same pair of cities. Similarly, no two railways connect the same pair of cities.
We will say city A and B are connected by roads if city B is reachable from city A by traversing some number of roads. Here, any city is considered to be connected to itself by roads. We will also define connectivity by railways similarly.
For each city, find the number of the cities connected to that city by both roads and railways.

Constraints
2≤N≤2*105
1≤K,L≤105
1≤pi,qi,ri,si≤N
pi < qi
ri < si
When i≠j, (pi,qi)≠(pj,qj)
When i≠j, (ri,si)≠(rj,sj)
输入
The input is given from Standard Input in the following format:
N K L
p1 q1
:
pK qK
r1 s1
:
rL sL
输出
Print N integers. The i-th of them should represent the number of the cities connected to the i-th city by both roads and railways.
样例输入
4 3 1
1 2
2 3
3 4
2 3
样例输出
1 2 2 1
提示
All the four cities are connected to each other by roads.
By railways, only the second and third cities are connected. Thus, the answers for the cities are 1,2,2 and 1, respectively.

题意:有N个城市,k个公路,L个铁路,使得城市之间相连,我们认为1-2,2-3,3-4三条公路时,1,2,3,4都是用公路联通的,铁路同理,求每个城市既被公路联通,又同时用铁路联通的城市个数,定义每个城市都自己联通自己。在上面的样例1,2,3,4中,若此时有一条铁路1-4,即认为,城市1,用铁路和公路联通的城市数量为2,城市4也为2,即城市自己联通自己,和对方。

首先我们对公路进行一次并查集建图,可以得到公路时所有城市的联通块,再对铁路进行一次并查集,可以得到铁路的联通块,对于每两个城市,在铁路和公路两个图中,若有同样的boss,即,城市A和城市B,在铁路中联通,在公路中也联通,可以认为他们是用两种交通方式联通的。如果直接用并查集合并求和,肯定是会超时的,因此反过来想,我们对于每个城市,知道他的boss,那么直接让他自己去找boss记录就行了,如何合并两个并查集中的boss计数呢?此时,我们不关心也不能关心他们在两个图中是否是同一个boss,因为并查集不能限定boss的定义是谁,那么只需要认为,两城市分别在两个图中具有相同的boss即可,并不是说A,B两市在铁路图中BOSS是C城市,在公路中的BOSS都是D城市,就不能认为他们不连通。因此我们直接对每个城市的BOSS出现进行计数即可。需要用map哈希来合并两图BOSS出现的计数。

最后输出每个城市BOSS的计数结果即可。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn=1e5+10;
const LL has=5e5;
int n,l,k;
int road[2*maxn],rail[2*maxn];
int find(int z[],int x)///比while式的查找更优秀,路径压缩也更快
{
    return z[x]==x?x:z[x]=find(z,z[x]);
}
void join(int z[],int x,int y)
{
    int a=find(z,x),b=find(z,y);
    if(a!=b) z[a]=b;
}
map<LL,int>ans;
int main()
{
    while(scanf("%d%d%d",&n,&k,&l)!=EOF)
    {
        ans.clear();
        for(int i=0; i<=n; i++)rail[i]=i,road[i]=i;
        int from,to;
        for(int i=0; i<k; i++)
        {
            scanf("%d%d",&from,&to);
            join(road,from,to);
        }
        for(int i=0; i<l; i++)
        {
            scanf("%d%d",&from,&to);
            join(rail,from,to);
        }
        for(int i=1;i<=n;i++)ans[(LL)find(road,i)*has+(LL)find(rail,i)]++;
        for(int i=1; i<=n; i++)printf("%d%c",ans[find(road,i)*has+find(rail,i)],i==n?'\n':' ');
    }
}
/*
4 2 2
1 3
2 3
1 4
2 4
*/

猜你喜欢

转载自blog.csdn.net/kuronekonano/article/details/80519186
UPC
今日推荐