問題文
N 個の都市があり、K 本の道路と L 本の鉄道が都市の間に伸びています。 i 番目の道路は pi 番目と qi 番目の都市を双方向に結び、 i 番目の鉄道は ri 番目と si 番目の都市を双方向に結びます。 異なる道路が同じ 2 つの都市を結ぶことはありません。同様に、異なる鉄道が同じ 2 つの都市を結ぶことはありません。
ある都市から別の都市に何本かの道路を通って到達できるとき、それらの都市は道路で連結しているとします。また、すべての都市はそれ自身と道路で連結しているとみなします。
鉄道についても同様に定めます。
全ての都市について、その都市と道路・鉄道のどちらでも連結している都市の数を求めてください。
制約
2≦N≦2*105
1≦K,L≦105
1≦pi,qi,ri,si≦N
pi<qi
ri<si
i≠j のとき、(pi,qi)≠(pj,qj)
i≠j のとき、(ri,si)≠(rj,sj)
入力
入力は以下の形式で標準入力から与えられる。
N K L
p1 q1
:
pK qK
r1 s1
:
rL sL
出力
N 個の整数を出力せよ。i 番目の数は i 番目の都市と道路・鉄道の両方で連結している都市の数である。
入力例 1
4 3 1
1 2
2 3
3 4
2 3
出力例 1
1 2 2 1
1,2,3,4 番目の都市は全て互いに道路で連結しています。
鉄道で連結している都市は 2,3 のみなので、答えは順に 1,2,2,1 となります。
入力例 2
4 2 2
1 2
2 3
1 4
2 3
出力例 2
1 2 2 1
入力例 3
7 4 4
1 2
2 3
2 5
6 7
3 5
4 5
3 4
6 7
出力例 3
1 1 2 1 2 2 2
题意:给出n个点,k条公路,l条铁路,构成一张无向图。定义i-j如果既能只通过铁路到达又能通过公路到达,则f[i]++とf[j]++,输出f[i](1<=i<=n)
题解:将只保留公路的图称之为A,只保留铁路的称之为B,AB均由一些内部可以两两互相到达的点集组成,假设点x在A集的第i个点集中,点x在B集的第j个点集中,则能对点x产生贡献的是所有在A中i集和B中j集的所有点个数,这可以用并查集维护。
代码如下:
#include<map> #include<ctime> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define mp make_pair using namespace std; map<pair<int,int>,int> m; struct dsu { int fa[200010],rank[200010]; void init(int n) { for(int i=1;i<=n;i++) { fa[i]=i; } } int find(int x) { if(fa[x]==x) { return x; } return fa[x]=find(fa[x]); } void union_(int x,int y) { int fx=find(x); int fy=find(y); if(fx==fy) { return ; } if(rank[fx]<rank[fy]) { fa[fx]=fy; } else { fa[fy]=fx; if(rank[fx]==rank[fy]) { rank[x]++; } } } int same(int x,int y) { return find(x)==find(y); } }a,b; int main() { //give the fucking vjudge a flying fucking int n,x,y; scanf("%d%d%d",&n,&x,&y); a.init(n); b.init(n); int from,to; for(int i=1;i<=x;i++) { scanf("%d%d",&from,&to); a.union_(from,to); } for(int i=1;i<=y;i++) { scanf("%d%d",&from,&to); b.union_(from,to); } for(int i=1;i<=n;i++) { m[mp(a.find(i),b.find(i))]++; } for(int i=1;i<=n;i++) { printf("%d ",m[mp(a.find(i),b.find(i))]); } }