弱省互测#2 t2
题意
给两个树,大小分别为n和m,现在两棵树各选一些点(包括1),使得这棵树以1号点为根同构(同构就是每个点的孩子数目相同),求最大的同构树。(n, m<=500)
分析
我们从两棵树中各取出一个点,考虑以这两个点为根能得到的最大同构数。
题解
容易得到:
设\(d(i, j)\)表示第一棵树选\(i\)号点,第二棵树选\(j\)号点所能得到的最大同构数。
那么\(d(i, j)\)就是等于从\(i\)这个点的子树选一些点,从\(j\)这个点的子树选一些点,选出的点数目相同,一一匹配,则答案就是这些点的\(\sum d(x, y)\)。
计算这个我们用最大费用流来计算。
同时我们从深度深的向深度浅的进行计算。
#include <bits/stdc++.h>
using namespace std;
const int N=505, M=N*2;
int ed[2][N][N], ecnt[2][N], n[2], ihead[M], cnt=1;
struct E {
int next, from, to, cap, w;
}e[M*M];
void add(int x, int y, int cap, int w) {
e[++cnt]=(E){ihead[x], x, y, cap, w}; ihead[x]=cnt;
e[++cnt]=(E){ihead[y], y, x, 0, -w}; ihead[y]=cnt;
}
int d[M], p[M];
bool spfa(int s, int t, int n) {
static bool vis[M];
static int q[M], fr, ta;
fr=ta=0;
q[ta++]=s;
memset(d, 0x7f, sizeof(int)*(n+1));
d[s]=0;
while(ta!=fr) {
int x=q[fr++];
vis[x]=0;
fr=fr==M?0:fr;
for(int i=ihead[x]; i; i=e[i].next) {
if(!e[i].cap) {
continue;
}
int y=e[i].to;
if(d[y]>d[x]+e[i].w) {
d[y]=d[x]+e[i].w;
p[y]=i;
if(!vis[y]) {
vis[y]=1;
if(d[y]<d[q[fr]]) {
fr=fr==0?M:fr;
q[--fr]=y;
}
else {
q[ta++]=y;
ta=ta==M?0:ta;
}
}
}
}
}
return d[t]!=0x7f7f7f7f;
}
void tadd(int x, int y, int w) {
ed[w][x][ecnt[w][x]++]=y;
ed[w][y][ecnt[w][y]++]=x;
}
int st[2][N][N], scnt[2][N], mxdep;
void dfs(int w, int x, int f, int dep) {
st[w][dep][scnt[w][dep]++]=x;
mxdep=max(dep, mxdep);
int sz=0;
for(int i=0; i<ecnt[w][x]; ++i) {
int y=ed[w][x][i];
if(y==f) {
continue;
}
dfs(w, y, x, dep+1);
ed[w][x][sz++]=y;
}
ecnt[w][x]=sz;
}
int f[N][N];
void work(int x, int y) {
int c1=ecnt[0][x], c2=ecnt[1][y];
int s=c1+c2+1, t=s+1;
memset(ihead, 0, sizeof(int)*(t+1));
cnt=1;
for(int i=1; i<=c1; ++i) {
add(s, i, 1, 0);
}
for(int i=1; i<=c2; ++i) {
add(c1+i, t, 1, 0);
}
for(int i=0; i<c1; ++i) {
for(int j=0; j<c2; ++j) {
int y1=ed[0][x][i], y2=ed[1][y][j];
add(i+1, c1+j+1, 1, -f[y1][y2]);
}
}
int &now=f[x][y];
now=1;
while(spfa(s, t, t)) {
int f=0x7f7f7f7f;
for(int x=t; x!=s; x=e[p[x]].from) f=min(f, e[p[x]].cap);
for(int x=t; x!=s; x=e[p[x]].from) e[p[x]].cap-=f, e[p[x]^1].cap+=f;
now+=-f*d[t];
}
}
void dfs(int dep) {
if(dep<0) {
return;
}
int c1=scnt[0][dep], c2=scnt[1][dep];
for(int i=0; i<c1; ++i) {
for(int j=0; j<c2; ++j) {
work(st[0][dep][i], st[1][dep][j]);
}
}
dfs(dep-1);
}
int main() {
scanf("%d", &n[0]);
for(int i=1; i<n[0]; ++i) {
int x, y;
scanf("%d%d", &x, &y);
tadd(x, y, 0);
}
scanf("%d", &n[1]);
for(int i=1; i<n[1]; ++i) {
int x, y;
scanf("%d%d", &x, &y);
tadd(x, y, 1);
}
dfs(0, 1, 0, 0);
dfs(1, 1, 0, 0);
dfs(mxdep);
printf("%d\n", f[1][1]);
return 0;
}
弱省互测#2 t2的更多相关文章
- 弱省互测#0 t2
题意 给定两个字符串 A 和 B,求下面四个问题的答案: 1.在 A 的子串中,不是 B 的子串的字符串的数量. 2.在 A 的子串中,不是 B 的子序列的字符串的数量. 3.在 A 的子序列中,不是 ...
- 【CH 弱省互测 Round #1 】OVOO(可持久化可并堆)
Description 给定一颗 \(n\) 个点的树,带边权. 你可以选出一个包含 \(1\) 顶点的连通块,连通块的权值为连接块内这些点的边权和. 求一种选法,使得这个选法的权值是所有选法中第 \ ...
- 弱省互测#2 t3
题意 给出\(n\)个01字节和\(m\)个01字节,要求用后者去匹配前者,两个串能匹配当且仅当除了每个字节末位不同,其他位都要相同.问匹配后者至少有多少个末位不同.(\(1 \le m \le n ...
- 弱省互测#1 t3
题意 给出一棵n个点的树,求包含1号点的第k小的连通块权值和.(\(n<=10^5\)) 分析 k小一般考虑堆... 题解 堆中关键字为\(s(x)+min(a)\),其中\(s(x)\)表示\ ...
- 弱省互测#0 t3
Case 1 题意 要求给出下面代码的答案然后构造输入. 给一个图, n 个点 m 条边 q 次询问,输出所有点对之间最大权值最小的路径. 题解 把每一个询问的输出看成一条边,建一棵最小生成树. Ca ...
- 弱省互测#0 t1
题意 给一个\(N \times M\)的01网格,1不能走,从起点\((1, 1)\)走到\((N, M)\),每次只能向下或向右走一格,问两条不相交的路径的方案数.(n, m<=1000) ...
- 【2018集训队互测】【XSY3372】取石子
题目来源:2018集训队互测 Round17 T2 题意: 题解: 显然我是不可能想出来的……但是觉得这题题解太神了就来搬(chao)一下……Orzpyz! 显然不会无解…… 为了方便计算石子个数,在 ...
- 【loj2461】【2018集训队互测Day 1】完美的队列
#2461. 「2018 集训队互测 Day 1」完美的队列 传送门: https://loj.ac/problem/2461 题解: 直接做可能一次操作加入队列同时会弹出很多数字,无法维护:一个操作 ...
- 洛谷 P4463 - [集训队互测 2012] calc(多项式)
题面传送门 & 加强版题面传送门 竟然能独立做出 jxd 互测的题(及其加强版),震撼震撼(((故写题解以祭之 首先由于 \(a_1,a_2,\cdots,a_n\) 互不相同,故可以考虑求出 ...
随机推荐
- Android学习资料收集
1.Android 学习之路 http://stormzhang.com/android/2014/07/07/learn-android-from-rookie/
- Tsinsen A1486. 树(王康宁)
Description 一棵树,问至少有 \(k\) 个黑点的路径最大异或和. Sol 点分治. 用点分治找重心控制树高就不说了,主要是对答案的统计的地方. 将所有路径按点的个数排序. 可以发现当左端 ...
- asp.net4.5尚未在web服务器上注册 解决方案
以前都是直接用aspnet_regiis.exe -i 现在用这个不好使了,解决办法打微软补丁. https://blogs.msdn.microsoft.com/webdev/2014/11/11/ ...
- 通过挂载系统光盘搭建本地yum仓库的方法
在CentOS系统中,我们常常会安装大量的软件,但许多软件包都存在需要依赖性,当然我们可以通过一一安装依赖包来完成安装,但对于有些软件包需要大量的依赖包,再一一安装起来会显得特别麻烦.接下来我们就来讲 ...
- 解决Mysql连接池被关闭 ,hibernate尝试连接不能连接的问题。 (默认mysql连接池可以访问的时间为8小时,如果超过8小时没有连接,mysql会自动关闭连接池。系统发布第二天访问链接关闭问题。
解决Mysql连接池被关闭 ,hibernate尝试连接不能连接的问题. (默认MySQL连接池可以访问的时间为8小时,如果超过8小时没有连接,mysql会自动关闭连接池. 所以系统发布第二天访问会 ...
- tp5 中 model 的修改器
修改器可以在数据赋值的时候自动进行转换处理 class User extends Model { public function setNameAttr($value){ return strtolo ...
- iOS之开发小技巧
1.xcode如何添加快捷代码 xcode添加快捷代码 属性 2.cocoapods安装 cocoapods安装 3.iOS真机调试 真机调试 4.命令行自动打包 xcrun -sdk iphoneo ...
- centos7.0 下安装git(http方式)
之前弄了个ssh方式访问的git服务器,但是那种方式不太方便,而且网页也访问不了,所以这里又弄个http方式访问的git服务器. 安装过程还和之前一样,这里我再复制一遍,省的再去找了. 1. 安装依赖 ...
- git pull push 不用输入用户名和密码的方法
1.在计算机的安装盘下找到 '用户' 这个文件夹打开. 2.找到'用户' 文件夹下面你当前的用户. 3.新建'.gitconfig' 文件 4. [user] email = name = [pus ...
- QuartZ2D __ 简单用法 1
一. 简单做一个画板 1. 建立一个UIView类 2. 在.m里建立一个延展 3. 分别定义一个起点, 一个终点的结构体属性 . 在建立一个存储路径的数组 @interface DrawView ( ...