bzoj 3197 DP
这道题我们可以看成给定两个黑白树,可以修改其中一棵树的颜色,问最少修改多少颜色可以使两棵树同构。
首先我们知道在树的同构中树上最长链中点(如果是偶数的话就是中间两个点)是不变的,我们把这个点叫做树的重心(如果有两个重心bz,by的话我们可以加一个点连接bx,by,将加的这个点看成重心),那么我们可以以树的重心为根来DP。
我们可以处理使x,y为根的子树同构的最小代价,判断树同构的合法性我们可以递归的判断每一个儿子的size来判断,设x,y的子节点sonx,sony,那么假设我们求出了所有sonx,sony的值,我们可以得到状态表示,f[s]代表y子树中我们已经匹配了s集合的子节点,x子树中我们已经匹配了前|s|个节点,现在要用x子树的第|s|+1节点匹配y子树中的其他未匹配节点,然后用sonx和sony的值来更新答案。
/**************************************************************
Problem: 3197
User: BLADEVIL
Language: C++
Result: Accepted
Time:576 ms
Memory:884 kb
****************************************************************/
//By BLADEVIL
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 800
#define inf (~0U>>1) using namespace std; int n,mx,go,bx,by,rot;
int g[maxn][],a[maxn],b[maxn],s[maxn],c[maxn],f[maxn]; void dfs(int x,int fa,int dep) {
s[++s[]]=x;
if (dep>mx) {
mx=dep; go=x;
memcpy(c,s,sizeof s);
}
for (int i=;i<=g[x][];i++)
if (g[x][i]!=fa) dfs(g[x][i],x,dep+);
s[]--;
} void build(int x,int fa) {
int t[]; t[]=;
for (int i=;i<=g[x][];i++)
if (g[x][i]!=fa&&!(x==bx&&g[x][i]==by||x==by&&g[x][i]==bx))
t[++t[]]=g[x][i];
memcpy(g[x],t,sizeof t);
for (int i=;i<=g[x][];i++) build(g[x][i],x);
} int dp(int x,int y) {
if (g[x][]!=g[y][]) return inf;
int w[][];
for (int i=;i<=g[x][];i++)
for (int j=;j<=g[y][];j++)
w[i][j]=dp(g[x][i],g[y][j]);
for (int i=;i<<<g[x][];i++) f[i]=inf;
f[(<<g[x][])-]=;
for (int i=(<<g[x][])-;i;i--) {
if (f[i]<inf) {
int cnt=g[x][];
for (int j=;j<g[x][];j++)
if (i&(<<j)) cnt--;
for (int j=;j<g[x][];j++)
if (i&(<<j))
f[i^(<<j)]=min(f[i^(<<j)],f[i]+w[cnt+][j+]);
}
}
return f[]+(a[x]!=b[y]);
} int main() {
scanf("%d",&n);
for (int i=;i<n;i++) {
int x,y; scanf("%d%d",&x,&y);
g[x][++g[x][]]=y;
g[y][++g[y][]]=x;
}
for (int i=;i<=n;i++) scanf("%d",&a[i]);
for (int i=;i<=n;i++) scanf("%d",&b[i]);
dfs(,,);
dfs(go,mx=,);
if (c[]&) rot=c[+c[]>>]; else {
rot=n+;
bx=g[rot][++g[rot][]]=c[c[]>>];
by=g[rot][++g[rot][]]=c[(c[]>>)+];
}
build(rot,);
//for (int i=1;i<=n;i++) printf("%d\n",g[i][0]);
printf("%d\n",dp(rot,rot));
return ;
}
bzoj 3197 DP的更多相关文章
- bzoj 3622 DP + 容斥
LINK 题意:给出n,k,有a,b两种值,a和b间互相配对,求$a>b$的配对组数-b>a的配对组数恰好等于k的情况有多少种. 思路:粗看会想这是道容斥组合题,但关键在于如何得到每个a[ ...
- bzoj 3197 [Sdoi2013]assassin(Hash+DP+KM)
Description Input Output Sample Input 4 1 2 2 3 3 4 0 0 1 1 1 0 0 0 Sample Output 1 HINT [思路] Hash,D ...
- BZOJ 3197: [Sdoi2013]assassin 树形DP + 最小费用流 + 树的同构
Description Input Output 其实就是给出两颗树,求一种两种树同构的方式,使得不同颜色个数最少$.$树的重新构建,其实就是指定不同的点为根节点$.$ 好在树的重心有一个重要的性质: ...
- BZOJ - 1003 DP+最短路
这道题被马老板毒瘤了一下,TLE到怀疑人生 //然而BZOJ上妥妥地过了(5500ms+ -> 400ms+) 要么SPFA太玄学要么是初始化block被卡到O(n^4) 不管了,不改了 另外D ...
- BZOJ 2431 & DP
题意:求逆序对数量为k的长度为n的排列的个数 SOL: 显然我们可以对最后一位数字进行讨论,判断其已经产生多少逆序对数量,然后对于前n-1位同样考虑---->每一个长度的排列我们都可以看做是相同 ...
- bzoj 1791 DP
首先对于一棵树我们可以tree_dp来解决这个问题,那么对于环上每个点为根的树我们可以求出这个树的一端为根的最长链,并且在tree_dp的过程中更新答案.那么我们对于环,从某个点断开,破环为链,然后再 ...
- bzoj 1592 dp
就是dp啊 f[i][j]表示到第i位,最后一位高度是j的最小花费 转移::f[i][j]=minn(f[i-1][k])+abs(a[i]-num[j]);(k<=j) #include< ...
- BZOJ 1207 DP
打一次鼹鼠必然是从曾经的某一次打鼹鼠转移过来的 以打每一个鼹鼠时的最优解为DP方程 #include<iostream> #include<cstdio> #include&l ...
- bzoj 1925 dp
思路:dp[ i ][ 0 ]表示第一个是山谷的方案,dp[ i ][ 1 ]表示第一个是山峰的方案, 我们算dp[ x ][ state ]的时候枚举 x 的位置 x 肯定是山峰, 然后就用组合数算 ...
随机推荐
- 无法打开mfc120.lib
今天在用VS2013编译OSG的时候报错:无法打开mfc120.lib.仔细查了下资料. 我是这么解决的: 安装Multibyte MFC Library for Visual Studio 2013 ...
- Zigbee安全基础篇Part.1
原文地址: https://www.4hou.com/wireless/14211.html 导语:ZigBee是一种开源无线技术,用于低功耗嵌入式设备(无线电系统).本文探讨了ZigBee协议的可用 ...
- 201621044079WEEK作业08-集合
作业08-集合 1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 如 ...
- hadoop2.5.2学习及实践笔记(五)—— HDFS shell命令行常见操作
附:HDFS shell guide文档地址 http://hadoop.apache.org/docs/r2.5.2/hadoop-project-dist/hadoop-common/FileSy ...
- C++ 普通函数和虚函数调用的区别
引出:写个类A,声明类A指针指向NULL,调用类A的方法会有什么后果,编译通过吗,运行会通过吗? #include<stdio.h> #include<iostream> us ...
- Spring Boot 最简单的HelloWorld
创建一个Spring Boot,可以直接使用构建工具(Maven或Gradle)创建,也可以使用spring.io网站创建,一般会选择使用spring.io创建 使用IDEA创建一个Spring Bo ...
- hdu3625-Rooms
题目 有\(n\)个房间,\(n\)个钥匙,每个钥匙随机出现在一个房间里,一个房间里有且仅有一个钥匙.我们现在手上没有钥匙,但我们要搜索所有的房间,所以我们有\(k\)次机会把一个房间炸开.一号房间里 ...
- C# 面向对象——多态
多态分三种:1.虚方法 2.抽象类 3.接口 1.虚方法1.将父类的方法标记为虚方法 ,使用关键字 virtual,这个函数可以被子类重新写一个遍. 如: class Program { static ...
- 【题解】CF#983 E-NN country
首先,我们从 u -> v 有一个明显的贪心,即能向上跳的时候尽量向深度最浅的节点跳.这个我们可以用树上倍增来维护.我们可以认为 u 贪心向上跳后不超过 lca 能跳到 u' 的位置, v 跳到 ...
- 【题解】SDOI2009Bill的挑战
这题好像状压的做法比较的无脑?但想记录一下容斥的做法,感觉自己对于容斥简直一无所知.这道题目容斥的解法我也是看了题解才会的.如有雷同,是我看的(*/ω\*)我们可以首先枚举当前字符串与给定的哪 \(k ...