Atcoder Beginner Contest152F(DFS+状压DP)

二维状压写成一维状压,省略加上第i条边这一维

 1 #define HAVE_STRUCT_TIMESPEC
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 vector<pair<int,int> >v[57];
 5 long long dp[1<<20];
 6 int x[57];
 7 bool dfs(int now,int fa,int root,int pos){//当前结点,父节点,终结点,所在边编号
 8     if(now==root)
 9         return 1;
10     for(auto it:v[now]){
11         if(it.first!=fa&&dfs(it.first,now,root,pos)){
12             x[it.second]^=1<<pos;
13             return 1;
14         }
15     }
16     return 0;
17 }
18 int main(){
19     ios::sync_with_stdio(false);
20     cin.tie(NULL);
21     cout.tie(NULL);
22     int n;
23     cin>>n;
24     for(int i=1;i<n;++i){
25         int a,b;
26         cin>>a>>b;
27         v[a].emplace_back(b,i);
28         v[b].emplace_back(a,i);
29     }
30     int m;
31     cin>>m;
32     for(int i=0;i<m;++i){
33         int a,b;
34         cin>>a>>b;
35         dfs(a,0,b,i);//遍历a和b中间的所有结点,即遍历两点之间所有边
36     }
37     dp[0]=1;//所有的边全白
38     for(int i=1;i<n;++i)//每次添加一条边
39         for(int j=(1<<m)-1;j>=0;--j)//状压DP,从后往前是为了避免重复加
40             dp[j|x[i]]+=dp[j];//dp【j状态|加入第i条边变黑能满足的状态x[i]】+=dp【第i条边加入之前的状态j】
41     cout<<dp[(1<<m)-1];//全状态
42     return 0;
43 }

 

posted @ 2020-01-29 18:01  sewage  阅读(237)  评论(0编辑  收藏  举报