• Codeforces Gym 100463E Spies 并查集


    Spies

    Time Limit: 20 Sec

    Memory Limit: 256 MB

    题目连接

    http://codeforces.com/gym/100463/attachments

    Description

    In the aftermath of Canada’s annexation of Pittsburgh tensions have been pretty high between Canada and the US. You have personally been hired by the US government to track down a number of Canadian spies. Through CIA intelligence the location of a number of spies is partially known. Specifically the CIA knows there are N (1 ≤ N ≤ 100000) spies and have narrowed down each spy to one or two locations. ”Oh My Golly!” exclaims the president. ”There could be as many as 2N possible arrangments for the spies”! ”Not quite, Mr. President. You see the Canadian government would not waste resources by sending two spies to the same location.” Now the task comes to. You are to compute how many ways the spies could be arranged. As this number could be quite large compute it modulo 1, 000, 000, 007.

    Input

    Input will consist of multiple test cases. The first line of each case will contain N and M separated by a space (1 ≤ N, M ≤ 100, 000) giving the number of spies and the number of cities respectively. After that will be N lines each containing two integers u and v (0 ≤ u, v < M) indicating the two possible locations of a spy. Interpret lines where u = v as indicating the spy is known to be at location u. The input is terminated with a line containing two zeroes.

    Output

    For each test case output the case number followed by the number of ways the spies could be arranged modulo 1, 000, 000, 007. Two arrangements are considered different if any spy has a different location. If there is no way to arrange the spies in different cities output 0. Follow the format in the sample output.

    Sample Input

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

    Sample Output

    Case 1: 6 Case 2: 0

    HINT

    题意

    有一堆人,每个人可能存在两个地方,每个地方最多一个人,然后问你有多少种情况

    题解:

    看起来好麻烦,我当成dp搞了好久……Orz

    结果是一个并查集就好了,把人都连边处理成链状,然后就吼了!

    代码

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <set>
    #include <vector>
    #include <sstream>
    #include <queue>
    #include <typeinfo>
    #include <fstream>
    #include <map>
    #include <stack>
    typedef long long ll;
    using namespace std;
    //freopen("D.in","r",stdin);
    //freopen("D.out","w",stdout);
    #define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
    #define test freopen("test.txt","r",stdin)
    const int maxn=102501;
    #define mod 1000000007
    #define eps 1e-9
    const int inf=0x3f3f3f3f;
    const ll infll = 0x3f3f3f3f3f3f3f3fLL;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    //**************************************************************************************
    
    int fa[maxn];
    bool uni[maxn];
    int num[maxn];
    int n,m;
    int sz[maxn];
    int fi(int x)
    {
        return fa[x]==x?x:fa[x]=fi(fa[x]);
    }
    void me(int x,int y)
    {
        int rx=fi(x),ry=fi(y);
        uni[rx]|=uni[ry];//如果有一个确定了,那么显然与他合并的都确定了
        num[rx]++;
        if(x==y)
        {
            uni[rx]=1;
            return;
        }
        if(rx!=ry)
        {
            sz[rx]+=sz[ry];
            num[rx]+=num[ry];
        }
        fa[ry]=rx;
    }
    int solve()
    {
        int res=1;
        for(int i=0;i<m;i++)
        {
            if(fa[i]==i)
            {
                if(num[i]>sz[i])
                    return 0;
                if(num[i]==sz[i])
                    res=res*(uni[i]?1ll:2ll)%mod;
                else
                    res=1ll*res*sz[i]%mod;
            }
        }
        return res%mod;
    }
    int main()
    {
        int t=0;
        while(scanf("%d%d",&n,&m)==2)
        {
            t++;
            if(n==0&&m==0)
                break;
            for(int i=0;i<m;i++)
                fa[i]=i;
            for(int i=0;i<m;i++)
                sz[i]=1;
            memset(num,0,sizeof(num));
            memset(uni,0,sizeof(uni));
            //上面都是奇怪的初始化
            for(int i=1;i<=n;i++)
            {
                int x=read(),y=read();
                me(x,y);
            }
            printf("Case %d: %d
    ",t,solve());
        }
    }
  • 相关阅读:
    Linux学习篇(四):学习 gdb
    Linux学习篇(三):学习 gcc
    c#序列化感悟(重点讲讲二进制序列化)
    参数保存随笔
    写程序时try,catch查看报错的行号
    stram流char[]保存,支持中文,Filestram需要先转byte[]才能使用,但是性能更好《转载》
    c#序列化和反序列化《转载》
    如果两个测量设备出现相关性数据问题,且过度像素没区别?(打光效果一致),怎么办
    当Hobject类型出现内存泄漏爆炸增长的问题,怎么处理
    使用gige2500万相机时遇见的问题(条纹以及取图过久)
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4665583.html
Copyright © 2020-2023  润新知