zoukankan      html  css  js  c++  java
  • 四校联考 独立集

    题目有点长,就贴过来好了。

    计算一张给定的图的最大独立集不是一件容易的事情。 它往往需要一个比较高的复杂度来实现。 因此, 我们经常使用随机的办法来试图求出独立集:随意一个点的排列, 按顺序考察每个点。 如果将当前的点纳入独立集中不会引起冲突(即不存在某条边的两端均入选的情况), 则将这个点加入独立集中。 按照这种办法得到的独立集可能不是点数最多的, 所以我们经常将上面的操作重复进行多次, 从中选取点数最多的一次。

    现在考虑一棵n个点的树。如果使用上述办法来求它的独立集, 并且只进行一次, 我们所得到的独立集的期望点数是多少?

    输入树,n<=200,mod 1e9+7。

    考虑这样dp,记f[i][j][sta]为i的子树中第j时刻(0...sz[i])i的状态为sta的pair(方案数,点数总和),sta有三种:0父亲最终在独立集中、1父亲最终不在独立集中,自己当前不在独立集中、2自己当前已经在独立集中了。

    子树合并的时候sta有三种:0本身最终在独立集中,1本身最终不在独立集中,孩子们当前都不在独立集中,2孩子已经有若干在独立集中了。

    转移自己脑补一下...

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <time.h>
    #include <stdlib.h>
    #include <string>
    #include <bitset>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <sstream>
    #include <stack>
    #include <iomanip>
    using namespace std;
    #define pb push_back
    #define mp make_pair
    typedef pair<int,int> pii;
    typedef long long ll;
    typedef double ld;
    typedef vector<int> vi;
    #define fi first
    #define se second
    #define fe first
    #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
    #define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
    #define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
    #define es(x,e) (int e=fst[x];e;e=nxt[e])
    #define esb(x,e,b) (int e=fst[x],b=vb[e];e;e=nxt[e],b=vb[e])
    #define VIZ {printf("digraph G{
    "); for(int i=1;i<=n;i++) for es(i,e) printf("%d->%d;
    ",i,vb[e]); puts("}");}
    #define VIZ2 {printf("graph G{
    "); for(int i=1;i<=n;i++) for es(i,e) if(vb[e]>=i)printf("%d--%d;
    ",i,vb[e]); puts("}");}
    #define SZ 666666
    int n,sz[SZ]; Edg
    const int MOD=1e9+7;
    typedef pair<ll,ll> fn;
    fn operator * (fn a,fn b)
    {return fn(a.fi*b.fi%MOD,(a.fi*b.se+a.se*b.fi)%MOD);}
    fn operator + (fn a,fn b)
    {return fn((a.fi+b.fi)%MOD,(a.se+b.se)%MOD);}
    fn operator + (fn a,ll b)
    {return fn(a.fi,(a.se+a.fi*b)%MOD);}
    fn operator * (fn a,ll b)
    {return fn(a.fi*b%MOD,a.se*b%MOD);}
    ll C[2333][2333];
    fn f[555][555][3],t[555][3],tmp[555][3],qzh[555][3],hzh[555][3];
    void dfs(int x,int fa)
    {
        for esb(x,e,b) if(b!=fa) dfs(b,x);
        int s=0; t[s][0]=t[s][1]=fn(1,0);
        t[s][2]=pii(0,0); sz[x]=0;
        for esb(x,e,b) if(b!=fa)
        {
            for(int i=0;i<=sz[x]+sz[b];++i)
                memset(tmp[i],0,sizeof tmp[0]);
            for(int i=0;i<=sz[x];++i)
                for(int j=0;j<=sz[b];++j)
                {
                    ll s=C[i+j][i]*C[sz[x]+sz[b]-i-j][sz[x]-i]%MOD;
                    tmp[i+j][0]=tmp[i+j][0]+t[i][0]*f[b][j][0]*s;
                    tmp[i+j][1]=tmp[i+j][1]+t[i][1]*f[b][j][1]*s;
                    tmp[i+j][2]=tmp[i+j][2]+t[i][1]*f[b][j][2]*s
                    +t[i][2]*f[b][j][1]*s+t[i][2]*f[b][j][2]*s;
                }
            sz[x]+=sz[b];
            for(int i=0;i<=sz[x]+sz[b];++i)
                memcpy(t[i],tmp[i],sizeof tmp[0]);
        }
        ++sz[x]; memcpy(qzh[0],t[0],sizeof t[0]);
        for(int i=1;i<sz[x];++i)
            for(int r=0;r<3;++r)
                qzh[i][r]=qzh[i-1][r]+t[i][r];
        memset(hzh[sz[x]],0,sizeof hzh[0]);
        for(int i=sz[x]-1;i>=0;--i)
            for(int r=0;r<3;++r)
                hzh[i][r]=hzh[i+1][r]+t[i][r];
        for(int i=0;i<=sz[x];++i)
        {
            if(i)
                f[x][i][0]=f[x][i][1]=qzh[i-1][2],
                f[x][i][2]=qzh[i-1][0]+1;
            else f[x][i][0]=f[x][i][1]=f[x][i][2]=pii(0,0);
            f[x][i][0]=f[x][i][0]+hzh[i][1]+hzh[i][2];
            f[x][i][1]=f[x][i][1]+(hzh[i][0]+1)+hzh[i][2];
        }
    }
    int main()
    {
        for(int i=0;i<2333;++i)
        {
            C[i][0]=1;
            for(int j=1;j<=i;++j)
                C[i][j]=(C[i-1][j-1]+C[i-1][j])%MOD;
        }
        int T; scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n); M=0;
            for(int i=1;i<=n;++i) fst[i]=0;
            for(int i=1;i<n;++i)
            {
                int a,b;
                scanf("%d%d",&a,&b);
                adde(a,b);
            }
            dfs(1,0);
            ll ans=f[1][n][0].se+f[1][n][2].se;
            ans=(ans%MOD+MOD)%MOD;
            printf("%d
    ",int(ans));
        }
    }

  • 相关阅读:
    嵊泗
    窗函数介绍
    射频与微波测量之失真参数
    C# 文件与路径操作
    史密斯圆图
    Winform 关闭Form而不销毁Form的内存
    射频与微波测量之S参数
    东极岛
    C#中正则表达式解析字符串信息
    射频微波相关公式
  • 原文地址:https://www.cnblogs.com/zzqsblog/p/7473252.html
Copyright © 2011-2022 走看看