Little Star "ZJOI2016"

The meaning of problems

Given a graph, and tree. Seeking the tree node renumbered, the number of species that can be covered by the map? The number of nodes ≤17.


Thinking

Consider the simple tree dp.

Sub-state is set \ (DP [i] [J] [s] \) , i represents the number of node j, the set of points comprising the subtree composed of the number of species s.

The time complexity of the transfer is \ (O (n3 the n-^) \) , is the perfect card.

Consider limiting conditions given topic:

  1. A node number can only be programmed once.

  2. Each side of the tree must appear in the original graph.

If there is no first limit, then we can eliminate the third dimension, the transfer equation is as follows: \ [DP [I] [J] = \ {Pi_ K \ in subtree} \ sum_ {T} ^ n-DP. 1 = [K ] [t] \]

On this basis, we consider the first constraint.

When a node number is repeated, there will certainly be no other nodes are numbered, then we can not enumerate every point of which is numbered.

Statistics last time the answer is no -1 0 +2 no no - . .

Total time complexity is \ (O (n2 the n-^) \) , just ran.

Code

#include <bits/stdc++.h>

using namespace std;

namespace StandardIO {

    template<typename T>inline void read (T &x) {
        x=0;T f=1;char c=getchar();
        for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
        for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
        x*=f;
    }

    template<typename T>inline void write (T x) {
        if (x<0) putchar('-'),x*=-1;
        if (x>=10) write(x/10);
        putchar(x%10+'0');
    }

}

using namespace StandardIO;

namespace Project {
    #define int long long
    
    const int N=20;
    
    int n,m,ans;
    int cnt;
    int head[N];
    struct node {
        int from,to,next;
    } edge[N<<1];
    int G[N][N];
    int left[N],dp[N][N];
    
    inline int count (int x) {
        int res=0;
        while (x) {
            if (x&1) ++res;
            x>>=1;
        }
        return res;
    }
    inline void add (int a,int b) {
        edge[++cnt].from=a,edge[cnt].to=b,edge[cnt].next=head[a],head[a]=cnt;
    }
    void dfs (int now,int fa) {
        for (register int i=1; i<=n; ++i) {
            if (left[i]) dp[now][i]=0;
            else dp[now][i]=1;
        }
        for (register int i=head[now]; i; i=edge[i].next) {
            int to=edge[i].to;
            if (to==fa) continue;
            dfs(to,now);
            for (register int j=1; j<=n; ++j) {
                if (left[j]) continue;
                int tmp=0;
                for (register int k=1; k<=n; ++k) {
                    if (G[j][k]&&!left[k]) tmp+=dp[to][k];
                }
                dp[now][j]*=tmp;
            }
        }
    }
    
    inline void MAIN () {
        read(n),read(m);
        for (register int i=1; i<=m; ++i) {
            int x,y;read(x),read(y);
            G[x][y]=G[y][x]=1;
        }
        for (register int i=1; i<n; ++i) {
            int x,y;read(x),read(y);
            add(x,y),add(y,x);
        }
        for (register int s=0; s<(1<<n); ++s) {
            for (register int i=0; i<n; ++i) {
                left[i+1]=s&(1<<i);
            }
            dfs(1,1);
            int tmp=0;
            for (register int i=1; i<=n; ++i) {
                tmp+=dp[1][i];
            }
            if (count(s)%2==0) ans+=tmp;
            else ans-=tmp;
        }
        write(ans);
    }
    
    #undef int
}

int main () {
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    Project::MAIN();
}

Guess you like

Origin www.cnblogs.com/ilverene/p/11479578.html