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 2018 Multi-University Training Contest 3
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;
}