zoukankan      html  css  js  c++  java
  • Atcoder 2159 連結 / Connectivity(并查集+map乱搞)

    問題文
    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))]);
        }
    }
  • 相关阅读:
    Hadoop学习资料收集
    sed使用详解
    shell编程001
    电影《无法触碰》
    正则表达式
    I/O重定向与管道
    bash基础知识
    用户权限模型
    Linux文件管理常用命令
    根文件系统详解
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/9015882.html
Copyright © 2011-2022 走看看