zoukankan      html  css  js  c++  java
  • dtoj2612 小星星(star)

    小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品。她有n颗小星星,用m条彩色的细线串了起来,每条细线连着两颗小星星。有一天她发现,她的饰品被破坏了,很多细线都被拆掉了。这个饰品只剩下了n-1条细线,但通过这些细线,这n颗小星星还是被串在一起,也就是这些小星星通过这些细线形成了树。

    小Y找到了这个饰品的设计图纸,她想知道现在饰品中的小星星对应着原来图纸上的哪些小星星。如果现在饰品中两颗小星星有细线相连,那么要求对应的小星星原来的图纸上也有细线相连。

    小Y想知道有多少种可能的对应方式。只有你告诉了她正确的答案,她才会把小饰品做为礼物送给你呢。


    Sol

    题目求树在图上有多少种对应方式。

     假设我们先不考虑每一个点只能映射一个点。(这步很关键!!使得状态好设计、转移)

    我们在最外层枚举点集S,表示树映射到了点集S或者S的子集的方案数。

    此时的映射树上两个不同的点可以对应图上的同一个点。

    我们考虑f[i][j]表示以i为根的子树,i对应的点是j。枚举i的儿子v对应点k,(j,k)要有边。

    考虑n个点映射但不合法的方案,一定有1个点未被映射。

    那么我们减去n-1个点被映射的方案。

    那么此时只映射n-2个点的方案被减了2次,要加上

    答案就是映射到n个点的方案数-映射n-1个点的方案数+映射n-2个点的方案数。

    我是想不出这种题的,好菜,还是得多做题。

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxn 20
    using namespace std;
    int n,m,s[maxn][maxn],head[maxn];
    int t1,t2,tot,dy[maxn],top;
    long long f[maxn][maxn],ans;
    struct node{
        int v,nex;
    }e[805];
    void lj(int t1,int t2){
        e[++tot].v=t2;e[tot].nex=head[t1];head[t1]=tot;    
    }
    void dfs(int k,int fa){
        for(int i=head[k];i;i=e[i].nex){
            if(e[i].v!=fa)dfs(e[i].v,k);
        }
        for(int i=1;i<=top;i++){
            f[k][i]=1;
            for(int j=head[k];j;j=e[j].nex){
                if(e[j].v==fa)continue;
                long long sum=0;
                for(int co=1;co<=top;co++){
                    if(s[dy[i]][dy[co]])sum+=f[e[j].v][co];
                }
                f[k][i]*=sum;if(!sum)break;
            }
        }
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&t1,&t2);
            s[t1][t2]=s[t2][t1]=1;
        }
        for(int i=1;i<n;i++){
            scanf("%d%d",&t1,&t2);
            lj(t1,t2);lj(t2,t1);    
        }
        for(int i=1;i<=((1<<n)-1);i++)
        {
            top=0;
            for(int j=0;j<n;j++)if(i&(1<<j))dy[++top]=j+1;
            dfs(1,0);
            long long fs=0;
            for(int j=1;j<=top;j++)fs+=f[1][j];
            if((n-top)%2==0)ans+=fs;
            else ans-=fs;
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    2011年全球手机市场十大事件
    异地求学催生网卖“生活费” 家长称不听话退款
    pygame库常用
    pygame_鼠标事件
    在Python和Django模板系统中的真值
    Django seeting配置(一)
    Django数据库配置
    转载CSS boxflex属性(弹性盒子模型)
    java volatile变量
    并发资料收集
  • 原文地址:https://www.cnblogs.com/liankewei/p/12301744.html
Copyright © 2011-2022 走看看