• Codeforces 859E Desk Disorder:并查集【两个属性二选一】


    题目链接:http://codeforces.com/problemset/problem/859/E

    题意:

      有n个人,2n个座位。

      给出这n个人初始的座位,和他们想坐的座位。

      每个人要么坐在原来的位置不动,要么坐到想坐的座位上,但是不能有两个人坐在同一个座位上。

      问你合法的安排座位的方案数。

    题解:

      将2n个座位抽象成2n个点。

      对于每个人,从他的初始位置向想坐的位置连一条边。

      总答案即为所有连通块答案的乘积。

      由于每一个点最多向外连一条边,所以对于每一个连通块只有三种情况:

        (1)是一棵树,根节点不自环,且所有边的方向都是由儿子指向父亲。

        (2)是一棵树,根节点自环,且所有边的方向都是由儿子指向父亲。

        (3)有且只有一个环。

      对于这三种情况,可以发现:

        (1)方案数 = 连通块大小siz[fa]

        (2)方案数 = 1

        (3)方案数 = 2

      并查集维护一下,最后统计答案即可。

    AC Code:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <algorithm>
     5 #define MAX_N 200005
     6 #define MOD 1000000007
     7 
     8 using namespace std;
     9 
    10 int n;
    11 int par[MAX_N];
    12 int siz[MAX_N];
    13 bool tag[MAX_N];
    14 bool loop[MAX_N];
    15 long long ans=1;
    16 
    17 void init_union_find()
    18 {
    19     for(int i=1;i<=(n<<1);i++)
    20     {
    21         par[i]=i;
    22         siz[i]=1;
    23         tag[i]=false;
    24         loop[i]=false;
    25     }
    26 }
    27 
    28 int find(int x)
    29 {
    30     return par[x]==x ? x : par[x]=find(par[x]);
    31 }
    32 
    33 void unite(int x,int y)
    34 {
    35     int px=find(x);
    36     int py=find(y);
    37     if(px==py)
    38     {
    39         tag[px]=true;
    40         return;
    41     }
    42     siz[py]+=siz[px];
    43     tag[py]|=tag[px];
    44     par[px]=py;
    45 }
    46 
    47 void read()
    48 {
    49     cin>>n;
    50     init_union_find();
    51     int x,y;
    52     for(int i=1;i<=n;i++)
    53     {
    54         cin>>x>>y;
    55         unite(x,y);
    56         if(x==y) loop[x]=true;
    57     }
    58 }
    59 
    60 void work()
    61 {
    62     for(int i=1;i<=(n<<1);i++)
    63     {
    64         if(find(i)==i)
    65         {
    66             if(loop[i]) continue;
    67             if(tag[i]) ans=(ans<<1ll)%MOD;
    68             else ans=ans*siz[i]%MOD;
    69         }
    70     }
    71     cout<<ans<<endl;
    72 }
    73 
    74 int main()
    75 {
    76     read();
    77     work();
    78 }
  • 相关阅读:
    VS.net 2005快捷键一览表
    POJ 1141 Brackets Sequence
    POJ 3264 Balanced Lineup RMQ问题的ST解法
    Hdu 4267 A Simple Problem with Integers
    hdu 4009 Transfer water
    HDU 4288 Coder
    POJ 1679 The Unique MST
    hdu 4291 A Short problem
    hdu 1175 连连看(DFS)
    POJ 3164 Command Network
  • 原文地址:https://www.cnblogs.com/Leohh/p/8473751.html
Copyright © 2020-2023  润新知