洛谷P3296 刺客信条
题意:
给你一棵树,有两组01权值a[]和b[]。n <= 700
你要构造一个自己到自己的映射,使得整棵树的形态不变,且映射后的a[]和映射之前的b[]中不同元素尽量少。
解:
发现这个整棵树形态不变......我们可能要用到树hash。
有个结论就是两棵树同构,当且仅当以它们重心为根的时候hash值相同。有两个重心就新建一个虚重心。
于是我们把重心搞出来当根,考虑映射之后的树,如果a映射到了b,那么a和b一定深度相同且hash值相同。
于是我们就按照深度分层,每层枚举点对,用f[a][b]来表示把点a映射到点b,子树内最少的不同元素。
于是如何求f[a][b]?发现我们要给a和b的若干个子节点进行匹配,要求权值最小。二分图匹配即可。我采用费用流实现。
复杂度:O(n³ + n * 网络流),这个复杂度是我猜的...
#include <bits/stdc++.h> const int N = , MO = , INF = 0x3f3f3f3f; struct Edge {
int nex, v;
bool del;
}edge[N << ]; int tp = ; int f[N][N], n, e[N], siz[N], val[N], h[N], aim[N], p[], top, small, root, root2, in_e[N], lm, in[N], d[N];
bool vis[];
std::vector<int> v[N]; inline void getp(int n) {
for(int i = ; i <= n; i++) {
if(!vis[i]) {
p[++top] = i;
}
for(int j = ; j <= top && i * p[j] <= n; j++) {
vis[i * p[j]] = ;
if(i % p[j] == ) {
break;
}
}
}
return;
} inline void add(int x, int y) {
tp++;
edge[tp].v = y;
edge[tp].del = ;
edge[tp].nex = e[x];
e[x] = tp;
return;
} void getroot(int x, int f) {
int large = ;
siz[x] = ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == f) {
continue;
}
in_e[y] = i;
getroot(y, x);
siz[x] += siz[y];
large = std::max(large, siz[y]);
}
large = std::max(large, n - siz[x]);
if(large < small) {
root = x;
root2 = ;
small = large;
}
else if(large == small) {
root2 = x;
}
return;
} void DFS_1(int x, int f) {
d[x] = d[f] + ;
v[d[x]].push_back(x);
lm = std::max(lm, d[x]);
h[x] = ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == f || edge[i].del) {
continue;
}
DFS_1(y, x);
siz[x] += siz[y];
h[x] = (h[x] + 1ll * h[y] * p[siz[y]] % MO) % MO;
}
return;
} namespace fl { struct Edge {
int nex, v, c, len;
Edge(int N = , int V = , int C = , int L = ) {
nex = N;
v = V;
c = C;
len = L;
}
}edge[]; int tp = ; int e[N], d[N], vis[N], Time, pre[N], flow[N], n, tot;
std::queue<int> Q; inline void add(int x, int y, int z, int w) {
//printf("addedge : x = %d y = %d z = %d w = %d \n", x, y, z, w);
edge[++tp] = Edge(e[x], y, z, w);
e[x] = tp;
edge[++tp] = Edge(e[y], x, , -w);
e[y] = tp;
return;
} inline bool SPFA(int s, int t) {
vis[s] = Time;
memset(d + , 0x3f, tot * sizeof(int));
flow[s] = INF;
d[s] = ;
Q.push(s);
while(Q.size()) {
int x = Q.front();
Q.pop();
vis[x] = ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(d[y] > d[x] + edge[i].len && edge[i].c) {
d[y] = d[x] + edge[i].len;
flow[y] = std::min(edge[i].c, flow[x]);
pre[y] = i;
if(vis[y] != Time) {
vis[y] = Time;
Q.push(y);
}
}
}
}
return d[t] < INF;
} inline void update(int s, int t) { int f = flow[t];
while(s != t) {
int i = pre[t];
edge[i].c -= f;
edge[i ^ ].c += f;
t = edge[i ^ ].v;
}
return;
} inline int solve(int x, int y) { int ans = , cost = ;
n = in[x] - (x != root);
int s = * n + , t = tot = s + ;
//printf("solve : x = %d y = %d n = %d \n", x, y, n);
memset(e + , , tot * sizeof(int));
tp = ; for(int i = ::e[x], cnt1 = ; i; i = ::edge[i].nex, ++cnt1) {
int u = ::edge[i].v;
//printf("u = %d \n", u);
if(::d[u] < ::d[x] || ::edge[i].del) {
--cnt1;
continue;
}
add(s, cnt1, , );
add(cnt1 + n, t, , );
for(int j = ::e[y], cnt2 = ; j; j = ::edge[j].nex, ++cnt2) {
int v = ::edge[j].v;
//printf(" v = %d \n", v);
if(::d[v] < ::d[y] || ::edge[j].del) {
--cnt2;
continue;
}
/// u v
if(f[u][v] > -INF) {
add(cnt1, n + cnt2, , f[u][v]);
} }
} ++Time;
while(SPFA(s, t)) {
//printf("inside --------------------- \n");
ans += flow[t];
cost += flow[t] * d[t];
update(s, t);
++Time;
} //printf("ans = %d cost = %d \n", ans, cost);
if(ans != n) {
return -INF;
}
else {
return cost + (val[x] != aim[y]);
}
}
} int main() { scanf("%d", &n);
for(int i = , x, y; i < n; i++) {
scanf("%d%d", &x, &y);
add(x, y);
add(y, x);
in[x]++;
in[y]++;
}
for(int i = ; i <= n; i++) {
scanf("%d", &val[i]);
}
for(int i = ; i <= n; i++) {
scanf("%d", &aim[i]);
}
root = root2 = ;
small = N;
getroot(, );
//printf("root 1 = %d root 2 = %d \n", root, root2); if(root2) {
++n;
int i;
if(edge[in_e[root] ^ ].v == root2) {
i = in_e[root];
}
else {
i = in_e[root2];
}
edge[i].del = edge[i ^ ].del = ;
add(n, root);
add(n, root2);
root = n;
in[n] = ;
}
/// //printf("root = %d \n", root); DFS_1(root, ); for(int d = lm; d >= ; d--) {
int len = v[d].size();
for(int i = ; i < len; i++) {
int x = v[d][i];
for(int j = ; j < len; j++) {
int y = v[d][j];
if(in[x] != in[y] || h[x] != h[y]) {
f[x][y] = -INF;
//printf("1 : ");
}
else {
//f[x][y] = KM::solve(x, y);
f[x][y] = fl::solve(x, y);
//printf("2 : ");
}
//printf("f %d %d = %d \n", x, y, f[x][y]);
}
}
} printf("%d\n", f[root][root]);
return ;
}
AC代码
洛谷P3296 刺客信条的更多相关文章
- Bzoj3197/洛谷3296 [SDOI2013]刺客信条assassin(树的重心+树Hash+树形DP+KM)
题面 Bzoj 洛谷 题解 (除了代码均摘自喻队的博客,可是他退役了) 首先固定一棵树,枚举另一棵树,显然另一棵树只有与这棵树同构才有可能产生贡献 如果固定的树以重心为根,那么另一棵树最多就只有重心为 ...
- 洛谷1640 bzoj1854游戏 匈牙利就是又短又快
bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...
- 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.
没有上司的舞会 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...
- 洛谷P1108 低价购买[DP | LIS方案数]
题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...
- 洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Label:二维数组前缀和 你够了 这次我用DP
题目背景 (USACO 5.3.4) 题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N ...
- 洛谷P1710 地铁涨价
P1710 地铁涨价 51通过 339提交 题目提供者洛谷OnlineJudge 标签O2优化云端评测2 难度提高+/省选- 提交 讨论 题解 最新讨论 求教:为什么只有40分 数组大小一定要开够 ...
- 洛谷P1371 NOI元丹
P1371 NOI元丹 71通过 394提交 题目提供者洛谷OnlineJudge 标签云端评测 难度普及/提高- 提交 讨论 题解 最新讨论 我觉得不需要讨论O long long 不够 没有取 ...
- 洛谷P1538迎春舞会之数字舞蹈
题目背景 HNSDFZ的同学们为了庆祝春节,准备排练一场舞会. 题目描述 在越来越讲究合作的时代,人们注意的更多的不是个人物的舞姿,而是集体的排列. 为了配合每年的倒计时,同学们决定排出——“数字舞蹈 ...
- 洛谷八月月赛Round1凄惨记
个人背景: 上午9:30放学,然后因为学校举办读书工程跟同学去书城选书,中午回来开始打比赛,下午又回老家,中间抽出一点时间调代码,回家已经8:50了 也许是7月月赛时“连蒙带骗”AK的太幸运然而因同学 ...
随机推荐
- 2019-11-12-浅谈-Windows-桌面端触摸架构演进
title author date CreateTime categories 浅谈 Windows 桌面端触摸架构演进 lindexi 2019-11-12 14:37:31 +0800 2019- ...
- nicescroll 使用与配置
使用// 1. 简单模式,设置html元素滚动 $(document).ready(function() { $("html").niceScroll(); }); // 2. 返 ...
- laravel框架5.5 连接redis和redis集群
'redis' => [ 'client' => 'predis', 'default' => [ 'host' => env('REDIS_HOST', '127.0.0.1 ...
- 最新MySQL5.7.3.0版本安装(图文版本)
转自:http://www.myexception.cn/mysql/1609536.html 可以从http://dev.mysql.com/downloads/下载MySQL服务器安装软件包,我下 ...
- iOS开发CGImage.h简介
1.前因 由于剪切图片用到下面方法,此方法属于CGImage.h中,通过创建CGImageRef像素位图,可以通过操作存储的像素位来编辑图片. /* Create an image using the ...
- FreeMarker 自定义 TemplateDirectiveModel(一)
FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出.FreeMarker 与 Web 容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP.它不 ...
- 接口Interface解耦的理解
定义一个接口 磁盘 interface Disk(){ void save(File file); } U盘和硬盘都是磁盘,都实现这个接口 class UDisk implement Disk ...
- PAT甲级——A1106 Lowest Price in Supply Chain
A supply chain is a network of retailers(零售商), distributors(经销商), and suppliers(供应商)-- everyone invo ...
- PAT甲级——A1094 The Largest Generation
A family hierarchy is usually presented by a pedigree tree where all the nodes on the same level bel ...
- diskpart
比如格式化成fat32 format fs=fat32 quick 比鼠标方便 如何使用: 打开cmd输入diskpart进入命令 首先 list disk 然后 然后 clean 然后 create ...