Dynamic Graph Matching 【状压dp】
来源
https://vjudge.net/contest/397452#problem/C
思路
n只有10,可以状态压缩n个点所有的状态。
dp[i]表示某种状态的取法个数。
设新加入的边为(u,v),状态转移:dp[i] -> dp[i ^ (1<<(u-1)) ^ (1<<(v-1))] , (i>>(u-1)&1 == 0 , i>>(v-1)&1 == 0)
设新删去的边为(u,v),状态转移:dp[i] -> dp[i ^ (1<<(u-1)) ^ (1<<(v-1))] , (i>>(u-1)&1 == 1 , i>>(v-1)&1 == 1)
预处理所有状态相应地边数k(二进制下1的个数除以2),可以加速防止卡常。
询问时遍历所有状态加入ans[k]中即可以统计出所有的答案。
代码
#include
using namespace std;
typedef long long ll;
const ll M=1e9+7;
ll dp[2010],num[2010],ans[20];
inline ll fmod(ll x,ll M){return x>=M?x%M:x;}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
for (int i=0; i<1024; i++){
int p=i;
while (p){
if (p&1) num[i]++;
p>>=1;
}
num[i]>>=1;
}
int t;
cin>>t;
while (t--){
int n,m;
cin>>n>>m;
for (int i=0; i<(1<>op>>u>>v;
if (op[0]=='+'){
for (int i=0; i<(1<>(u-1))&1) && !((i>>(v-1))&1)){
int j=i^(1<<(u-1))^(1<<(v-1));
dp[j]=fmod(dp[j]+dp[i],M);
}
}
}
if (op[0]=='-'){
for (int i=0; i<(1<>(u-1))&1) && ((i>>(v-1))&1)){
int j=i^(1<<(u-1))^(1<<(v-1));
dp[i]=fmod(dp[i]-dp[j]+M,M);
}
}
}
for (int i=1; i<=(n>>1); i++) ans[i]=0;
for (int i=0; i<(1<>1); i++){
if (i!=1) cout<<" ";
cout<