Description

故事发生在1486 年的意大利,Ezio 原本只是一个文艺复兴时期的贵族,后来因为家族成员受到圣殿骑士的杀害,决心成为一名刺客。最终,凭借着他的努力和出众的天赋,成为了杰出的刺客大师,他不仅是个身手敏捷的武林高手,飞檐走壁擅长各种暗杀术。刺客组织在他的带领下,为被剥削的平民声张正义,赶跑了原本统治意大利的圣殿骑士首领-教皇亚历山大六世。在他的一生中,经历了无数次惊心动魄、扣人心弦的探险和刺杀。

曾经有一次,为了寻找Altair 留下的线索和装备,Ezio 在佛罗伦萨中的刺客墓穴进行探索。这个刺客墓穴中有许多密室,且任何两个密室之间只存在一条唯一的路径。这些密室里都有一个刺客标记,他可以启动或者关闭该刺客标记。为了打开储存着线索和装备的储藏室,Ezio 必须操作刺客标记来揭开古老的封印。要想解开这个封印,他需要通过改变某些刺客标记的启动情况,使得所有刺客标记与封印密码“看起来一样”。在这里,“看起来一样”

的定义是:存在一种“标记”密室与“密码”密室之间一一对应的关系,使得密室间的连接情况和启动情况相同(提示中有更详细解释)。幸运的是,在Ezio 来到刺客墓穴之前,在Da Vinci 的帮助下,Ezio 已经得知了打开储藏室所需要的密码。

而你的任务则是帮助Ezio 找出达成目标所需要最少的改动标记次数。

Input

第一行给出一个整数n,表示密室的个数。

第二行至第n 行,每行给出两个整数a 和b,表示第a 个密室和第b 个密室之间存在一条通道。

第n+1 行,给出n 个整数,分别表示当时每个密室的启动情况(0 表示关闭,1 表示启动)。

第n+2 行,给出n 个整数,分别表示密码中每个密室的启动情况。

Output

输出只有一行,即输出最少改动标记次数。

Sample Input

4
1 2
2 3
3 4
0 0 1 1
1 0 0 0

Sample Output

1

Data Constraint

对于30%的数据,n<=10。

对于60%的数据,n<=100。

对于100%的数据,n<=700,且每个密室至多与11 个密室相通。

Hint

样例解释:

密室的编号是可以变的!将第三个密室关闭后,在当前标记和密码之间,存在1->4,2->3,3->2,4->1 的对应关系,重新编号后连接情况没有改变,且标记与密码对应。对于更一般的情况,存在一个1 到n 的置换P,使得对于任意密室之间的道路u-v,都一定有密码密室中的道路P(u)-P(v);如果不存在密室之间的道路u-v,则一定没有密码密室中的道路P(u)-P(v)。

分析

看懂题意后思路会较为清晰虽然我也讲不清楚,请dalao们感性理解

针对题目的动态根,我们可以考虑两棵树同用一个根,然后同构树有个神奇的性质:如果使强制使两棵树的重心为根,那么这两棵树同构当且仅当这两棵有根树同构

但是重心可能有两个呢,我们只需要断开两个重心之间的边,然后新建一个点连向两个重心,新点就是新重心了

我们可以想到树中同深度同构的部分可以交换以减少代价

同构?树哈希咯

处理出每个点的哈希值后,我们设f[u][v]为以u为根的子树和以v为根的子树同构,且完成u子树的初始状态到v子树的最终状态的最小代价

显然这个要从他们的儿子处转移上来

然后我们可以发现,转移的过程就是选择这两棵子树中的若干对点,选择一对的代价为f[su][sv],使总代价最小

这是个带权二分图,可用KM算法或费用流算法解决

建议使用KM,费用流算法需要注意空间大小,代码复杂

#include <iostream>
#include <cstdio>
#include <memory.h>
#include <algorithm>
#include <queue>
using namespace std;
const int N=7e2+10;
const int P=76447;
struct Graph {int u,v,nx;
}g[2*N];
struct Cube {int u,v,nx,c,w;
}t[2*N*N+4*N];
int cnt,list[N],vis[2*N],dep[N],flow[2*N],dis[2*N],fa[2*N];
int g1,g2,sz[N],mxsize;
int h[N],xx[N],f[N][N],p[N];
int n,from[N],to[N],ans;void Add(int u,int v) {g[++cnt]=(Graph){u,v,list[u]};list[u]=cnt;g[++cnt]=(Graph){v,u,list[v]};list[v]=cnt;
}void Add_Cube(int u,int v,int w,int c) {t[++cnt]=(Cube){u,v,flow[u],c,w};flow[u]=cnt;t[++cnt]=(Cube){v,u,flow[v],0,-w};flow[v]=cnt;
}void Find_G(int u,int f) {int size=0;sz[u]=1;for (int i=list[u];i;i=g[i].nx)if (g[i].v!=f) {Find_G(g[i].v,u);sz[u]+=sz[g[i].v];size=max(size,sz[g[i].v]);}size=max(size,n-sz[u]);if (size==mxsize) g2=u;if (size<mxsize) {mxsize=size;g1=u;g2=0;}
}void Tree_Hash(int u,int f) {int xcnt=0;dep[u]=dep[f]+1;for (int i=list[u];i;i=g[i].nx) if (g[i].v!=f) Tree_Hash(g[i].v,u);for (int i=list[u];i;i=g[i].nx) if (g[i].v!=f) xx[++xcnt]=h[g[i].v];sort(xx+1,xx+xcnt+1);h[u]=17731;for (int i=1;i<=xcnt;i++) h[u]=(h[u]*7441%P+xx[i])%P;h[u]=h[u]*3119%P;
}bool CMP(int u,int v) {return dep[u]!=dep[v]?dep[u]>dep[v]:h[u]<h[v];
}bool SPFA() {queue<int> q;while (!q.empty()) q.pop();memset(dis,0x3f,sizeof dis);dis[0]=0;q.push(0);while (!q.empty()) {int u=q.front();q.pop();for (int i=flow[u];i;i=t[i].nx)if (dis[t[i].v]>dis[u]+t[i].w&&t[i].c) {dis[t[i].v]=dis[u]+t[i].w;fa[t[i].v]=i;if (!vis[t[i].v]) q.push(t[i].v);vis[t[i].v]=1;}vis[u]=0;}return dis[2*n+1]!=0x3f3f3f3f;
}void Get_Ans() {int x=2*n+1,mf=2147483647;while (fa[x]) {ans+=t[fa[x]].w;mf=min(mf,t[fa[x]].c);x=t[fa[x]].u;}x=2*n+1;while (fa[x]) {t[fa[x]].c-=mf;t[fa[x]^1].c+=mf;x=t[fa[x]].u;}
}int Min_Cost_Flow() {ans=0;while (SPFA()) Get_Ans();return ans;
}void DP() {for (int i=1;i<=n;i++) p[i]=i;sort(p+1,p+n+1,CMP);for (int i=1;i<=n;) {int j=i;for (;j<=n;j++)if (dep[p[i]]!=dep[p[j]]||h[p[i]]!=h[p[j]]) break;for (int k=i;k<j;k++)for (int l=i;l<j;l++) {int u=p[k],v=p[l];cnt=1;memset(flow,0,sizeof flow);for (int sv=list[v];sv;sv=g[sv].nx)if (dep[g[sv].v]==dep[v]+1)Add_Cube(n+g[sv].v,2*n+1,0,1);for (int su=list[u];su;su=g[su].nx)if (dep[g[su].v]==dep[u]+1) {Add_Cube(0,g[su].v,0,1);for (int sv=list[v];sv;sv=g[sv].nx)if (dep[g[sv].v]==dep[v]+1&&h[g[su].v]==h[g[sv].v])Add_Cube(g[su].v,n+g[sv].v,f[g[su].v][g[sv].v],1);}f[u][v]=Min_Cost_Flow()+(from[u]!=to[v]);}i=j;}
}int main() {scanf("%d",&n);for (int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),Add(u,v);for (int i=1;i<=n;i++) scanf("%d",&from[i]);for (int i=1;i<=n;i++) scanf("%d",&to[i]);mxsize=n;Find_G(1,0);if (g2) {cnt=0;memset(list,0,sizeof list);for (int i=1,j=1;i<=n-1;i++,j=i*2-1)if ((g[j].u!=g1||g[j].v!=g2)&&(g[j].v!=g1||g[j].u!=g2))Add(g[j].u,g[j].v);Add(g1,n+1),Add(n+1,g2);n++;g1=n;}Tree_Hash(g1,0);DP();printf("%d",f[g1][g1]);
}

View Code

转载于:https://www.cnblogs.com/mastervan/p/11104754.html

[哈希][费用流]JZOJ 3296 【SDOI2013】刺客信条相关推荐

  1. BZOJ3130: [Sdoi2013]费用流[最大流 实数二分]

    3130: [Sdoi2013]费用流 Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special Judge Submit: 960  Solved:  ...

  2. [SDOI2013]刺客信条

    Description 故事发生在1486 年的意大利,Ezio 原本只是一个文艺复兴时期的贵族,后来因为家族成员受到圣殿骑士的杀害,决心成为一名刺客.最终,凭借着他的努力和出众的天赋,成为了杰出的刺 ...

  3. [BZOJ 1221][HNOI2001]软件开发(费用流)

    Description 某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员 ...

  4. 费用流 -- 四川省赛F-Direction Setting [拆边成点+费用流]

    题目链接 题目大意: 就是给你一个nnn个点mmm条边的无向图,每个点有个值是aia_iai​现在你把每条边都赋予一个方向之后这个图就是有向图了,那么设第iii个点的入度是did_idi​,现在设 D ...

  5. UVA1411 Ants(带权二分图的最大完美匹配、zkw费用流)

    题解 给定一些黑点白点,要求一个黑点链接一个白点并且线段不相交(转成二分图最大权匹配使用费用流解决)<训练指南>P351 输出方案:满流即为答案(满流是指这条路的流量跑满了,也就是说edg ...

  6. 餐巾计划问题 线性规划与网络流24题之10 费用流

    相关知识:最小费用(最大)流 问题描述: 一个餐厅在相继的N 天里, 每天需用的餐巾数不尽相同. 假设第i天需要ri块餐巾(i=1, 2,-,N).餐厅可以购买新的餐巾,每块餐巾的费用为p分:或者把旧 ...

  7. BZOJ1150[CTSC2007]数据备份Backup——模拟费用流+堆+链表

    题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游 ...

  8. bzoj3171: [Tjoi2013]循环格(费用流)

    传送门 其实这题的建图并不难(虽然我并没有想出来) 首先,每一个点的入度和出度必须为$1$ 那么我们考虑拆点 每个点的出度点向它能到达的点的入度点连边,容量$1$,如果方向为原来的方向则费用$0$否则 ...

  9. 洛谷 - P2045 - 方格取数加强版 - 费用流

    原来这种题的解法是费用流. 从一个方格的左上走到右下,最多走k次,每个数最多拿走一次. 每次走动的流量设为1,起始点拆点成限制流量k. 每个点拆成两条路,一条路限制流量1,费用为价值相反数.另一条路无 ...

最新文章

  1. 【BZOJ2140】稳定婚姻 Tarjan
  2. HttpClient基础教程
  3. Bug只让变量生效一次的思路
  4. 06004_Redis的启动、使用和停止
  5. 深度学习(8)TensorFlow基础操作四: 维度变换
  6. oracle创建数据库用户并授权,oracle创建数据库、表空间、用户并授权
  7. phpStydy配置memcache扩展
  8. bzoj2208:[Jsoi2010]连通数
  9. vue 使用 ueditor uparse_vue手把手教学~搭建web聊天室
  10. AMPL—快速了解,秒懂它。
  11. ie调取摄像头抓拍解决方案
  12. “商圈合伙人”让异业联盟无边界化,打造共赢生态圈
  13. 论文查重颜色分别代表什么含义?
  14. 51nod1534 棋子游戏
  15. 电脑两个,电脑有两个系统盘怎么办
  16. excel表格如何不需鼠标往下拖动而自动往下填
  17. 计算机专业创新创业点,计算机专业学生创新能力培养
  18. Hi3516开发笔记(三):Hi3516虚拟机基础环境搭建之交叉编译环境境搭建以及开机启动脚本分析
  19. 悟空辅助显示连接服务器失败,悟空辅助的使用方法 第三期宠物助手
  20. vue2.x 标签动态设置背景问题,有透明度

热门文章

  1. ·乔布斯的接班人Tim Cook是神马人物
  2. word中插入带入带有上标和下标的字符串
  3. python设计tcp数据包协议类
  4. 物体碰撞,c#受力。
  5. 神经网络如何进行预测
  6. java request上传文件_java使用ServletFileUpload上传文件,ServletFileUpload.parseRequest(request)报错。...
  7. 怎么在Windows电脑上阅读epub小说,小说阅读器推荐
  8. 标志寄存器 CF PF AF ZF SF OF TF IF
  9. 多路视频实时全景拼接算法
  10. 网上的小段子,自己搞笑一下呵呵~~~