杭電多校第三場1003 C. Dynamic Graph Matching(狀壓dp 處理圖匹配計數)
Problem C. Dynamic Graph MatchingTime Limit: 8000/4000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 388 Accepted Submission(s): 148 Problem Description In the mathematical discipline of graph theory, a matching in a graph is a set of edges without common vertices. Input The first line of the input contains an integer T(1≤T≤10) , denoting the number of test cases. Output For each operation, print a single line containing n2 integers, denoting the answer for k=1,2,3,...,n2 . Since the answer may be very large, please print the answer modulo 109+7 .Sample Input 1 4 8 + 1 2 + 3 4 + 1 3 + 2 4 - 1 2 - 3 4 + 1 2 + 3 4 Sample Output 1 0 2 1 3 1 4 2 3 1 2 1 3 1 4 2 Source Recommend chendu | We have carefully selected several similar problems for you: 6331 6330 6329 6328 6327 |
【小結】
總碰到狀壓dp,總是束手無策。因為我菜。
【題意】
有一個n點的無向圖,初始時沒有邊,有m次操作,每次可以增加或刪除一條邊(注意,允許重邊的存在)
要求每一次操作之後,輸出匹配數分別為1,2,3...n/2的方案數。
匹配是指:選中一些邊,使得兩兩沒有公共點,即每兩個點可以通過邊匹配起來。
【分析】
二進位制表示集合,對於狀態 i 的每一位,為1則選中,為0則不屬於當前集合。
dp[i] 表示i狀態,集合內所有點都匹配了 的 方案數。
那麼當新增邊u-v時,所有同時包含 uv 的狀態 S 需要更新,dp[S] += dp[S-u-v] (S-u-v表示狀態S去掉u和v的狀態)
更新dp[i] 時,需要考慮更新時會對答案產生的貢獻。
【程式碼】
/****
***author: winter2121
****/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int MAX=2e5+5;
ll dp[1<<11]; //dp[i]:i集合內點完全匹配的方案數
int bit[1<<11]; //i的二進位制的1的個數
ll ans[11];
void adjust(ll &x){x=(x%mod+mod)%mod;}
int calc(int x)
{
int res=0;
while(x)res++,x-=x&-x;
return res;
}
int main()
{
for(int i=0;i<1<<10;i++)bit[i]=calc(i);
int T,n=10,m,u,v;
char op[3];
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
memset(dp,0,sizeof(dp));
memset(ans,0,sizeof(ans));
dp[0]=1;
while(m--)
{
scanf("%s%d%d",op,&u,&v);u--,v--;
if(op[0]=='+')
{
for(int i=(1<<n)-1;i>0;i--)if(((1<<u)&i)&&((1<<v)&i))
{
dp[i]+=dp[i-(1<<u)-(1<<v)];
ans[bit[i]]+=dp[i-(1<<u)-(1<<v)]; //對於i集合所有點的匹配,會對ans造成的影響
adjust(dp[i]);
adjust(ans[bit[i]]);
}
}
else
{
for(int i=1;i<1<<n;i++)if(((1<<u)&i)&&((1<<v)&i))
{
dp[i]-=dp[i-(1<<u)-(1<<v)];
ans[bit[i]]-=dp[i-(1<<u)-(1<<v)];
adjust(dp[i]);
adjust(ans[bit[i]]);
}
}
for(int i=2;i<=n;i+=2)
printf("%lld%c",ans[i],i==n?'\n':' ');
}
}
return 0;
}