参考ExtremeSpanningTrees,考虑优化整体二分时求$g_{i}\in \{w_{mid},w_{mid+1}\}$的最优解

对于$m=n-1$的问题,不需要去网络流,可以直接树形dp

但为了保证复杂度,我们在整体二分中的复杂度只能是$o(点集大小)$,这样可能就比较麻烦

首先要建出虚树(保留其中lca的点),并预处理出每一个点到深度最小的祖先使得其中边的方向都相同,之后就可以判断相邻两点是否有大小关系

对于$m=n$的问题,可以先暴力枚举基环上的一点,之后按照$m=n-1$的情况去做

  1. 1 #include<bits/stdc++.h>
  2. 2 using namespace std;
  3. 3 #define N 300005
  4. 4 #define ll long long
  5. 5 #define oo 1e15
  6. 6 #define u e[p][k][i]
  7. 7 #define y0 y00
  8. 8 vector<int>vv,e[2][N];
  9. 9 vector<pair<int,int> >ve;
  10. 10 int n,m,x,y,x0,y0,d[N],w[N],dfn[N],dep[N],las[N],g[N],fa[N][21],a[N],v[N],st[N],vis[N],bl[N],ans[N];
  11. 11 ll sum,f[N][2];
  12. 12 bool cmp1(int x,int y){
  13. 13 return dfn[x]<dfn[y];
  14. 14 }
  15. 15 bool cmp2(int x,int y){
  16. 16 return bl[x]<bl[y];
  17. 17 }
  18. 18 int find(int k){
  19. 19 if (k==fa[k][0])return k;
  20. 20 return fa[k][0]=find(fa[k][0]);
  21. 21 }
  22. 22 int lca(int x,int y){
  23. 23 if (dep[x]<dep[y])swap(x,y);
  24. 24 for(int i=20;i>=0;i--)
  25. 25 if (dep[fa[x][i]]>=dep[y])x=fa[x][i];
  26. 26 if (x==y)return x;
  27. 27 for(int i=20;i>=0;i--)
  28. 28 if (fa[x][i]!=fa[y][i]){
  29. 29 x=fa[x][i];
  30. 30 y=fa[y][i];
  31. 31 }
  32. 32 return fa[x][0];
  33. 33 }
  34. 34 void dfs(int k,int f,int s){
  35. 35 dfn[k]=++x;
  36. 36 dep[k]=s;
  37. 37 fa[k][0]=f;
  38. 38 for(int i=1;i<=20;i++)fa[k][i]=fa[fa[k][i-1]][i-1];
  39. 39 for(int p=0;p<2;p++)
  40. 40 for(int i=0;i<e[p][k].size();i++){
  41. 41 if (u==f)continue;
  42. 42 las[u]=p;
  43. 43 if (p^las[k])g[u]=s;
  44. 44 else g[u]=g[k];
  45. 45 dfs(u,k,s+1);
  46. 46 }
  47. 47 }
  48. 48 void dp(int k,int fa){
  49. 49 vis[k]=1;
  50. 50 for(int p=0;p<2;p++)
  51. 51 for(int i=0;i<e[p][k].size();i++)
  52. 52 if (u!=fa){
  53. 53 dp(u,k);
  54. 54 f[k][p^1]+=f[u][p^1];
  55. 55 f[k][p]+=min(f[u][0],f[u][1]);
  56. 56 }
  57. 57 }
  58. 58 void get_plan(int k,int fa,int type){
  59. 59 vis[k]=1;
  60. 60 if (type==2)type=(f[k][1]<f[k][0]);
  61. 61 bl[k]=type;
  62. 62 for(int p=0;p<2;p++)
  63. 63 for(int i=0;i<e[p][k].size();i++)
  64. 64 if (u!=fa){
  65. 65 if (p!=type)get_plan(u,k,type);
  66. 66 else get_plan(u,k,2);
  67. 67 }
  68. 68 }
  69. 69 void calc(int l,int r,int x,int y){
  70. 70 if (x==y){
  71. 71 for(int i=l;i<=r;i++)ans[a[i]]=v[x];
  72. 72 return;
  73. 73 }
  74. 74 sort(a+l,a+r+1,cmp1);
  75. 75 st[0]=0;
  76. 76 vv.clear();
  77. 77 ve.clear();
  78. 78 for(int j=l;j<=r;j++){
  79. 79 vv.push_back(a[j]);
  80. 80 if (!st[0]){
  81. 81 st[++st[0]]=a[j];
  82. 82 continue;
  83. 83 }
  84. 84 int k=lca(a[j],st[st[0]]);
  85. 85 while ((st[0]>1)&&(dep[k]==dep[lca(a[j],st[st[0]-1])])){
  86. 86 ve.push_back(make_pair(st[st[0]-1],st[st[0]]));
  87. 87 st[0]--;
  88. 88 }
  89. 89 if (st[st[0]]!=k){
  90. 90 vv.push_back(k);
  91. 91 ve.push_back(make_pair(k,st[st[0]]));
  92. 92 st[st[0]]=k;
  93. 93 }
  94. 94 st[++st[0]]=a[j];
  95. 95 }
  96. 96 for(int i=0;i<vv.size();i++){
  97. 97 e[0][vv[i]].clear(),e[1][vv[i]].clear();
  98. 98 vis[vv[i]]=f[vv[i]][0]=f[vv[i]][1]=0;
  99. 99 }
  100. 100 for(;st[0]>1;st[0]--)ve.push_back(make_pair(st[st[0]-1],st[st[0]]));
  101. 101 for(int i=0;i<ve.size();i++){
  102. 102 int xx=ve[i].first,yy=ve[i].second;
  103. 103 if (dep[xx]>=g[yy]){
  104. 104 e[las[yy]][xx].push_back(yy);
  105. 105 e[las[yy]^1][yy].push_back(xx);
  106. 106 }
  107. 107 }
  108. 108 int mid=(x+y>>1),tot=0;
  109. 109 for(int j=l;j<=r;j++){
  110. 110 if (a[j]==x0)tot++;
  111. 111 if (a[j]==y0)tot++;
  112. 112 }
  113. 113 if (tot<2){
  114. 114 for(int j=l;j<=r;j++){
  115. 115 f[a[j]][0]=1LL*abs(d[a[j]]-v[mid])*w[a[j]];
  116. 116 f[a[j]][1]=1LL*abs(d[a[j]]-v[mid+1])*w[a[j]];
  117. 117 }
  118. 118 for(int j=0;j<vv.size();j++)
  119. 119 if (!vis[vv[j]])dp(vv[j],0);
  120. 120 for(int j=0;j<vv.size();j++)vis[vv[j]]=0;
  121. 121 for(int j=0;j<vv.size();j++)
  122. 122 if (!vis[vv[j]])get_plan(vv[j],0,2);
  123. 123 }
  124. 124 else{
  125. 125 ll sum0=0,sum1=0;
  126. 126 for(int p=0;p<2;p++){
  127. 127 for(int j=l;j<=r;j++){
  128. 128 f[a[j]][0]=1LL*abs(d[a[j]]-v[mid])*w[a[j]];
  129. 129 f[a[j]][1]=1LL*abs(d[a[j]]-v[mid+1])*w[a[j]];
  130. 130 }
  131. 131 f[x0][p^1]=oo;
  132. 132 if (p)f[y0][0]=oo;
  133. 133 for(int j=0;j<vv.size();j++)
  134. 134 if (!vis[vv[j]]){
  135. 135 dp(vv[j],0);
  136. 136 if (!p)sum0+=min(f[vv[j]][0],f[vv[j]][1]);
  137. 137 else sum1+=min(f[vv[j]][0],f[vv[j]][1]);
  138. 138 }
  139. 139 for(int j=0;j<vv.size();j++)vis[vv[j]]=0;
  140. 140 }
  141. 141 if (sum0<sum1){
  142. 142 for(int j=l;j<=r;j++){
  143. 143 f[a[j]][0]=1LL*abs(d[a[j]]-v[mid])*w[a[j]];
  144. 144 f[a[j]][1]=1LL*abs(d[a[j]]-v[mid+1])*w[a[j]];
  145. 145 }
  146. 146 f[x0][1]=oo;
  147. 147 for(int j=0;j<vv.size();j++)
  148. 148 if (!vis[vv[j]])dp(vv[j],0);
  149. 149 for(int j=0;j<vv.size();j++)vis[vv[j]]=0;
  150. 150 }
  151. 151 for(int j=0;j<vv.size();j++)
  152. 152 if (!vis[vv[j]])get_plan(vv[j],0,2);
  153. 153 }
  154. 154 sort(a+l,a+r+1,cmp2);
  155. 155 for(int j=l;j<=r+1;j++)
  156. 156 if ((j>r)||(bl[a[j]])){
  157. 157 if (l<j)calc(l,j-1,x,mid);
  158. 158 if (j<=r)calc(j,r,mid+1,y);
  159. 159 return;
  160. 160 }
  161. 161 }
  162. 162 int main(){
  163. 163 scanf("%d%d",&n,&m);
  164. 164 for(int i=1;i<=n;i++)scanf("%d",&d[i]);
  165. 165 for(int i=1;i<=n;i++)scanf("%d",&w[i]);
  166. 166 for(int i=1;i<=n;i++)fa[i][0]=i;
  167. 167 for(int i=1;i<=m;i++){
  168. 168 scanf("%d%d",&x,&y);
  169. 169 if (find(x)==find(y))x0=x,y0=y;
  170. 170 else{
  171. 171 fa[x][0]=find(y);
  172. 172 e[0][x].push_back(y);
  173. 173 e[1][y].push_back(x);
  174. 174 }
  175. 175 }
  176. 176 x=0;
  177. 177 dfs(1,1,0);
  178. 178 memcpy(v,d,sizeof(v));
  179. 179 sort(v+1,v+n+1);
  180. 180 int nn=unique(v+1,v+n+1)-v-1;
  181. 181 for(int i=1;i<=n;i++)a[dfn[i]]=i;
  182. 182 calc(1,n,1,nn);
  183. 183 for(int i=1;i<=n;i++)sum+=1LL*w[i]*abs(d[i]-ans[i]);
  184. 184 printf("%lld",sum);
  185. 185 }

[loj2470]有向图的更多相关文章

  1. Kosaraju 算法检测有向图的强连通性

    给定一个有向图 G = (V, E) ,对于任意一对顶点 u 和 v,有 u --> v 和 v --> u,亦即,顶点 u 和 v 是互相可达的,则说明该图 G 是强连通的(Strong ...

  2. POJ 2337 Catenyms(有向图的欧拉通路)

    题意:给n个字符串(3<=n<=1000),当字符串str[i]的尾字符与str[j]的首字符一样时,可用dot连接.判断用所有字符串一次且仅一次,连接成一串.若可以,输出答案的最小字典序 ...

  3. code forces 383 Arpa's loud Owf and Mehrdad's evil plan(有向图最小环)

    Arpa's loud Owf and Mehrdad's evil plan time limit per test 1 second memory limit per test 256 megab ...

  4. 有向图强连通分量的Tarjan算法

    有向图强连通分量的Tarjan算法 [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G ...

  5. hdu1269迷宫城堡(判断有向图是否是一个强连通图)

    1 /* 题意: 给你一个图,求这个有向图示否是一个强连通图(每两个节点都是可以相互到达的)! 思路1:按正向边dfs一遍,将经过的节点计数,如果记录的节点的个数小于n,那么就说明图按照正向边就不是连 ...

  6. poj 1386 Play on Words(有向图欧拉回路)

    /* 题意:单词拼接,前一个单词的末尾字母和后一个单词的开头字母相同 思路:将一个单词的开头和末尾单词分别做两个点并建一条有向边!然后判断是否存在欧拉回路或者欧拉路 再次强调有向图欧拉路或欧拉回路的判 ...

  7. NYOJ 99单词拼接(有向图的欧拉(回)路)

    /* NYOJ 99单词拼接: 思路:欧拉回路或者欧拉路的搜索! 注意:是有向图的!不要当成无向图,否则在在搜索之前的判断中因为判断有无导致不必要的搜索,以致TLE! 有向图的欧拉路:abs(In[i ...

  8. 邻接表有向图(三)之 Java详解

    前面分别介绍了邻接表有向图的C和C++实现,本文通过Java实现邻接表有向图. 目录 1. 邻接表有向图的介绍 2. 邻接表有向图的代码说明 3. 邻接表有向图的完整源码 转载请注明出处:http:/ ...

  9. 邻接表有向图(二)之 C++详解

    本章是通过C++实现邻接表有向图. 目录 1. 邻接表有向图的介绍 2. 邻接表有向图的代码说明 3. 邻接表有向图的完整源码 转载请注明出处:http://www.cnblogs.com/skywa ...

随机推荐

  1. RabbitMQ的消息可靠性(五)

    一.可靠性问题分析 消息的可靠性投递是使用消息中间件不可避免的问题,不管是使用哪种MQ都存在这种问题,接下来要说的就是在RabbitMQ中如何解决可靠性问题:在前面 在前面说过消息的传递过程中有三个对 ...

  2. Go语言核心36讲(Go语言进阶技术一)--学习笔记

    07 | 数组和切片 我们这次主要讨论 Go 语言的数组(array)类型和切片(slice)类型. 它们的共同点是都属于集合类的类型,并且,它们的值也都可以用来存储某一种类型的值(或者说元素). 不 ...

  3. 初学Python-day12 装饰器函数

    装饰器 1.概念 本质就是一个Python函数,其他函数在本身不变的情况下去增加额外的功能,装饰器的返回值是一个函数. 常用的场景:插入日志,事务处理,缓存,权限校验等. 2.普通函数回顾 1 def ...

  4. 【UE4 C++】Print、Delay、ConsoleCommand

    基于UKismetSystemLibrary PrintString /** * Prints a string to the log, and optionally, to the screen * ...

  5. Spring Cloud Alibaba Nacos Config 的使用

    Spring Cloud Alibaba Nacos Config 的使用 一.需求 二.实现功能 1.加载 product-provider-dev.yaml 配置文件 2.实现配置的自动刷新 3. ...

  6. Noip模拟22 2021.7.21

    T1 d 简化题意就是找到相对平均长宽的偏移量较大的矩形给他删掉 可以说是个贪心,按照a,b分别为第一关键字排序 然后假装删去要求的那么多个按a排序的较小的,然后再去b中, 找到 删去的a中的那几个矩 ...

  7. 2021.10.15考试总结[NOIP模拟77]

    \(n=40\)考虑\(meet \;in \;the \;middle\) 某个元素有关的量只有一个时考虑转化为树上问题 对暴力有自信,相信数据有梯度 没了 UPD:写了个略说人话的. T1 最大或 ...

  8. 【BZOJ2070】列队春游———[组合数学+概率DP]

    数学渣滓不可做の题OTZ Description (单身人士不可做 Input                     |            Output 3                   ...

  9. vs2010中使用命令行参数

    使用VS2010增加命令参数的时候老是不起作用,后面经过研究发现,所要增加的命令参数是一个相对文件路径,而默认的工作目录里面没有该文件,所以就没有找到,需要修改工作目录,这样命令行参数才能够起作用.

  10. Pandas核心用法

    目录 Numpy和Pandas Numpy科学计算 Pandas数据分析 安装jupyter notebook Numpy语法 创建和基本使用 切片索引 布尔索引 对位运算 矩阵的乘除 其他方法 Pa ...