[LOJ2290] [THUWC2017] 隨機二分圖

題目連接

LOJ:https://loj.ac/problem/2290c++

洛谷:https://www.luogu.org/problemnew/show/P4547git

Solution

首先考慮只有第一類邊的狀況,那麼每種完美匹配必定會由\(n\)個邊組組成,機率就是\(1/2^n\),對答案貢獻爲\(1\),那麼問題就轉化成了統計完美匹配個數。spa

\(f[s1][s2]\)表示當前左邊狀況爲\(s1\),右邊爲\(s2\),在把其餘的點填滿能夠獲得的完美匹配的種類數,而後就是普及組\(dp\),複雜度\(O(2^{2n})\),可是這樣會重複計數,並且複雜度不對。code

若是咱們把\(s1\)嚴格每次都從高位到低位轉移,而後上記憶化搜索,複雜度能夠降到\(O(2^n\cdot n^2)\),且不會重複計數。get

考慮其餘兩類邊,咱們硬點這些邊都是單獨的,機率\(50\%\),可是這樣會算不對,第二類邊組在兩條邊都選的時候貢獻的機率爲\(25\%\),可是應該是\(50\%\),因此咱們多加一個\(25\%\)的邊組就行了,同理第三類邊組添加一個機率爲\(-25\%\)的邊組,而後改一改上面的\(dp\),記搜轉移就行了,\(f\)開不下能夠用\(\rm map\)it

#include<bits/stdc++.h>
using namespace std;

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}

void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

#define lf double
#define ll long long 

#define pii pair<int,int >
#define vec vector<int >

#define pb push_back
#define mp make_pair
#define fr first
#define sc second

#define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) 

const int maxn = 1e4+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 1e9+7;
const int inv2 = 5e8+4;
const int inv4 = 2.5e8+2;

int add(int x,int y) {return x+y>=mod?x+y-mod:x+y;}
int del(int x,int y) {return x-y<0?x-y+mod:x-y;}
int mul(int x,int y) {return 1ll*x*y-1ll*x*y/mod*mod;}

map<int,int > f;

int a[maxn],b[maxn],cnt,n,m;

int dfs(int s) {
    if(s==(1<<(n<<1))-1) return 1;
    if(f.find(s)!=f.end()) return f[s];int now=0,ans=0;
    for(int i=n-1;~i;i--) if(!(s&(1<<i))) {now=1<<i;break;}
    for(int i=1;i<=cnt;i++)
        if(!(a[i]&s)&&(now&a[i])) ans=add(ans,mul(b[i],dfs(s|a[i])));
    return f[s]=ans;
}

int main() {
    read(n),read(m);
    for(int i=1,s,s2,t,x,y;i<=m;i++) {
        read(t),read(x),read(y);x--,y--;
        s=1<<x|(1<<(y+n));a[++cnt]=s,b[cnt]=inv2;
        if(!t) continue;read(x),read(y);x--,y--;
        s2=1<<x|(1<<(y+n));a[++cnt]=s2,b[cnt]=inv2;
        if(s&s2) continue;
        a[++cnt]=s|s2,b[cnt]=t==1?inv4:mod-inv4;
    }write(mul(dfs(0),(int)pow(2,n)));
    return 0;
}
相關文章
相關標籤/搜索