zoukankan      html  css  js  c++  java
  • luogu P3349 [ZJOI2016]小星星

    题目链接

    发现要求的一一映射的条件可以转化为,图中的每个点至少被树上的点映射了一次。考虑对此进行容斥,每次限定一个集合内的数不可被映射,最后乘上容斥系数。

    (f[x][i]) 表示树上 (x) 被映射到 (i) 的方案数,则转移为:

    [f[x][i]=prod limits_{vin son}sumlimits_{jin S}map[i][j] imes f[v][j] ]

    其中 (S) 表示没有被限制的集合, (map) 的图的邻接矩阵。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #define int long long
    
    using namespace std;
    
    const int N = 20;
    int n, m, head[N], cnt, map[N][N], f[N][N];
    struct Edge
    {
    	int nxt, to;
    }g[N * N];
    
    void add(int from, int to)
    {
    	g[++cnt].nxt = head[from];
    	g[cnt].to = to;
    	head[from] = cnt;
    }
    
    void init()
    {
    	scanf("%lld %lld", &n, &m);
    	for (int i = 1, x, y; i <= m; i++)
    		scanf("%lld %lld", &x, &y), map[x][y] = map[y][x] = 1;
    	for (int i = 1, x, y; i < n; i++)
    		scanf("%lld %lld", &x, &y), add(x, y), add(y, x);
    }
    
    void calc(int x, int fa, int S)
    {
    	for (int i = 1; i <= n; i++)
    		if ((S & (1 << i - 1)) == 0)
    			f[x][i] = 1;
    		else
    			f[x][i] = 0;
    	for (int i = head[x]; i; i = g[i].nxt)
    	{
    		int v = g[i].to;
    		if (v == fa) continue;
    		calc(v, x, S);
    		for (int j = 1; j <= n; j++)
    		{
    			if ((S & (1 << j - 1))) continue;
    			int tmp = 0;
    			for (int k = 1; k <= n; k++)
    			{
    				if ((S & (1 << k - 1)) || !map[j][k]) continue;
    				tmp += f[v][k];
    			}
    			f[x][j] *= tmp;
    		}
    	}
    }
    
    void work()
    {
    	int ans = 0, MaxN = 1 << n;
    	for (int i = 0; i < MaxN; i++)
    	{
    		calc(1, -1, i);
    		int sum = 0, tmp = 0;
    		for (int j = 1; j <= n; j++)
    			if ((i & (1 << j - 1))) tmp++;
    			else sum += f[1][j];
    		tmp = (tmp & 1) ? -1 : 1;
    		ans = (ans + tmp * sum);
    	}
    	printf("%lld
    ", ans);
    }
    
    signed main()
    {
    	init();
    	work();
    	return 0;
    }
    
    
  • 相关阅读:
    链表相加
    Unity 摄像机跟随
    整数反转
    两数和
    频繁项集挖掘思路
    有关于二进制的乘法计算(原码一位乘)
    JAVA面向对象(下)
    JAVAAPI
    JAVA面向对象()上)
    JAVA基础第一章
  • 原文地址:https://www.cnblogs.com/With-penguin/p/13733771.html
Copyright © 2011-2022 走看看