1. 程式人生 > >P3043 [USACO12JAN]牛聯盟Bovine Alliance(並查集)

P3043 [USACO12JAN]牛聯盟Bovine Alliance(並查集)

connect conn esc sans int while bili bool void

P3043 [USACO12JAN]牛聯盟Bovine Alliance

題目描述

Bessie and her bovine pals from nearby farms have finally decided that they are going to start connecting their farms together by trails in an effort to form an alliance against the farmers. The cows in each of the N (1 <= N <= 100,000) farms were initially instructed to build a trail to exactly one other farm, for a total of N trails. However months into the project only M (1 <= M < N) of these trails had actually been built.

Arguments between the farms over which farms already built a trail now threaten to split apart the cow alliance. To ease tension, Bessie wishes to calculate how many ways the M trails that exist so far could have been built. For example, if there is a trail connecting farms 3 and 4, then one possibility is that farm 3 built the trail, and the other possibility is that farm 4 built the trail. Help Bessie by calculating the number of different assignments of trails to the farms that built them, modulo 1,000,000,007. Two assignments are considered different if there is at least one trail built by a different farm in each assignment.

給出n個點m條邊的圖,現把點和邊分組,每條邊只能和相鄰兩點之一分在一組,點可以單獨一組,問分組方案數。

輸入輸出格式

輸入格式:

  • Line 1: Two space-separated integers N and M

  • Lines 2..1+M: Line i+1 describes the ith trail. Each line contains two space-separated integers u_i and v_i (1 <= u_i, v_i <= N, u_i != v_i) describing the pair of farms connected by the trail.

輸出格式:

  • Line 1: A single line containing the number of assignments of trails to farms, taken modulo 1,000,000,007. If no assignment satisfies the above conditions output 0.

輸入輸出樣例

輸入樣例#1: 復制
5 4 
1 2 
3 2 
4 5 
4 5 
輸出樣例#1: 復制
6 

說明

Note that there can be two trails between the same pair of farms.

There are 6 possible assignments. Letting {a,b,c,d} mean that farm 1 builds trail a, farm 2 builds trail b, farm 3 builds trail c, and farm 4 builds trail d, the assignments are:

{2, 3, 4, 5} 
{2, 3, 5, 4} 
{1, 3, 4, 5} 
{1, 3, 5, 4} 
{1, 2, 4, 5} 
{1, 2, 5, 4} 



/*
可以並查集維護
可以發現,某個聯通快出現大於等於2個環,一定無法分配。
有解要麽一個環,要麽沒有環。
一個環時答案等於點數乘2(順時針或逆時針)。
沒有環是樹,對於一個n個點的樹,方案一定有n種(不連某個點)。
*/
#include<iostream>
#include<cstdio>
#include<cstring>

#define N 100007
#define mod 1000000007
#define ll long long

using namespace std;
ll n,m,ans,cnt;
ll fa[N],siz[N],num[N];
bool vis[N];

inline ll read()
{
    ll x=0,f=1;char c=getchar();
    while(c>9||c<0){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
    return x*f;
}

ll find(ll x){return x==fa[x]?x:fa[x]=find(fa[x]);}

void merge(ll x,ll y)
{
    fa[y]=x;
    siz[x]+=siz[y];num[x]+=num[y];
}

int main()
{
    ll x,y;ans=1;
    n=read();m=read();
    for(ll i=1;i<=n;i++) fa[i]=i,siz[i]=1;
    for(ll i=1;i<=m;i++)
    {
        x=read();y=read();
        ll r1=find(x),r2=find(y);
        if(r1!=r2) merge(r1,r2);
        else num[r1]++;
    } 
    for(ll i=1;i<=n;i++)
    {
        ll now=find(i);
        if(vis[now]) continue;vis[now]=1;
        if(num[now]>2) continue;
        if(num[now]==1) ans=(ans*2)%mod;
        if(!num[now]) ans=(ans*siz[now])%mod;
    }
    printf("%lld\n",ans%mod);
    return 0;
} 

 

P3043 [USACO12JAN]牛聯盟Bovine Alliance(並查集)