[ZJOI2016]小星星

来源:互联网 发布:手机wifi热点软件 编辑:程序博客网 时间:2024/06/10 09:21

强烈谴责毒瘤供题人K****供了题不会部分分
暴力1:O(n^n)。考虑每一个点是否合法。暴力dfs,判断点是否合法。选完n个点后ans++。
暴力2:考虑dp,首先保证方案合法性。dp[i][j]表示的是以i为根的子树中,使用了原图中那些点的状态。
(j是二进制串)
然后先dfs一遍预处理出初始情况,dp【i】【j】=1.
再dfs时暴力合并。枚举初始状态的子集、从初始状态(子集) 转移到 子树最大状态 合并上 当前节点初始状态。

转移方程形如 :f[u][i|j]+=f[v][j] // j是枚举的子集、i是初始状态的子集。

100分:计数问题考虑容斥。先不考虑合法性,f[i][j]计算在树中i节点被看作图中节点j的方案数。
发现ans=ban0个的-Σban任意1个的+Σban任意2个的。

以三个数为例。
用了1 2 3
-用了1 2 用了1 3 -用了2 3
显然多减了。
+用了1,用了2,用了3。

将选择的数组用二进制串(tmp数组)表达出来,当且仅当子树中的那个数,被看作的数与当前点被看作的数关系合法时才可以转移。树形DP即可。

#include<bits/stdc++.h>using namespace std;const int MAXN=50;#define ll long longstruct edge{    int to,next;}e[MAXN*MAXN*2];int head[MAXN],cnt=0,tmp[MAXN],num,n,m;ll f[MAXN][MAXN*MAXN];bool mmap[MAXN][MAXN];inline void add(int u,int v){e[++cnt]=(edge){v,head[u]},head[u]=cnt;}void dfs(int u,int fa){    for(int i=head[u];i;i=e[i].next){        int v=e[i].to;        if(v==fa)continue;        dfs(v,u);    }    for(int i=1;i<=num;i++){        f[u][i]=1;          for(int j=head[u];j;j=e[j].next){            int v=e[j].to;            if(v==fa)continue;            ll g=0;            for(int k=1;k<=num;k++){                if(mmap[tmp[i]][tmp[k]])g+=f[v][k];            }            f[u][i]*=g;        }    }}void dp(int u,int fa){    for(int i=head[u];i;i=e[i].next){        int v=e[i].to;        if(v==fa)continue;        dfs(v,u);    }    for(int i=1;i<=num;i++)    {          f[u][i]=1;          for(int j=head[u];j;j=e[j].next)        {            int v=e[j].to; long long t=0;            if(v!=fa)            {                for(int k=1;k<=num;k++)                    if(mmap[tmp[i]][tmp[k]])                        t+=f[v][k];                f[u][i]*=t;            }          }      }  }  int main(){    memset(mmap,0,sizeof(mmap));    memset(f,0,sizeof(f));    scanf("%d%d",&n,&m);    int limit=(1<<n)-1;    for(int i=1;i<=m;i++){        int u,v;        scanf("%d%d",&u,&v);        mmap[u][v]=mmap[v][u]=1;    }    for(int i=1;i<n;i++){        int u,v;        scanf("%d%d",&u,&v);        add(u,v);add(v,u);    }    ll ans=0;    for(int i=1;i<=limit;i++){        num=0;ll t=0;        for(int j=0;j<n;j++)if((i>>j)&1)tmp[++num]=j+1;        dfs(1,1);        for(int j=1;j<=num;j++)t+=f[1][j];//cout<<t;         ans+=(ll)((n-num)&1)?-t:t;    }    printf("%lld\n",ans);    return 0;} 
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 威锋ios源 威锋论坛4s 4s威锋论坛 iphone论坛威锋网 威锋网序列号查询 威锋论坛电子书资源分享区 威锋网iphone5s论坛 威锋网源是多少 威锋精品源地址 吉列威锋剃须刀 威锋网iphone4论坛 威锋论坛二手区 weiphone威锋网 威锋查序列号 iphone6 威锋 威锋 iphone5 威锋iphone查询 威锋网iphone5 威锋 iphone4s iphone5威锋网 威锋apple工具 威锋二手论坛 iphone5论坛威锋 威锋论坛 二手 iphone4 威锋 威锋论坛iphone4s iphone5威锋论坛 iphone4威锋网 威锋iphone4s论坛 iphone4s威锋论坛 威锋论坛iphone4 iphone6论坛 weifeng ios论坛 威风 weiphone 威峰手机论坛 威峰网 威峰 feng 威风网