[loj2470]有向图
参考ExtremeSpanningTrees,考虑优化整体二分时求$g_{i}\in \{w_{mid},w_{mid+1}\}$的最优解
对于$m=n-1$的问题,不需要去网络流,可以直接树形dp
但为了保证复杂度,我们在整体二分中的复杂度只能是$o(点集大小)$,这样可能就比较麻烦
首先要建出虚树(保留其中lca的点),并预处理出每一个点到深度最小的祖先使得其中边的方向都相同,之后就可以判断相邻两点是否有大小关系
对于$m=n$的问题,可以先暴力枚举基环上的一点,之后按照$m=n-1$的情况去做

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 300005
4 #define ll long long
5 #define oo 1e15
6 #define u e[p][k][i]
7 #define y0 y00
8 vector<int>vv,e[2][N];
9 vector<pair<int,int> >ve;
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 ll sum,f[N][2];
12 bool cmp1(int x,int y){
13 return dfn[x]<dfn[y];
14 }
15 bool cmp2(int x,int y){
16 return bl[x]<bl[y];
17 }
18 int find(int k){
19 if (k==fa[k][0])return k;
20 return fa[k][0]=find(fa[k][0]);
21 }
22 int lca(int x,int y){
23 if (dep[x]<dep[y])swap(x,y);
24 for(int i=20;i>=0;i--)
25 if (dep[fa[x][i]]>=dep[y])x=fa[x][i];
26 if (x==y)return x;
27 for(int i=20;i>=0;i--)
28 if (fa[x][i]!=fa[y][i]){
29 x=fa[x][i];
30 y=fa[y][i];
31 }
32 return fa[x][0];
33 }
34 void dfs(int k,int f,int s){
35 dfn[k]=++x;
36 dep[k]=s;
37 fa[k][0]=f;
38 for(int i=1;i<=20;i++)fa[k][i]=fa[fa[k][i-1]][i-1];
39 for(int p=0;p<2;p++)
40 for(int i=0;i<e[p][k].size();i++){
41 if (u==f)continue;
42 las[u]=p;
43 if (p^las[k])g[u]=s;
44 else g[u]=g[k];
45 dfs(u,k,s+1);
46 }
47 }
48 void dp(int k,int fa){
49 vis[k]=1;
50 for(int p=0;p<2;p++)
51 for(int i=0;i<e[p][k].size();i++)
52 if (u!=fa){
53 dp(u,k);
54 f[k][p^1]+=f[u][p^1];
55 f[k][p]+=min(f[u][0],f[u][1]);
56 }
57 }
58 void get_plan(int k,int fa,int type){
59 vis[k]=1;
60 if (type==2)type=(f[k][1]<f[k][0]);
61 bl[k]=type;
62 for(int p=0;p<2;p++)
63 for(int i=0;i<e[p][k].size();i++)
64 if (u!=fa){
65 if (p!=type)get_plan(u,k,type);
66 else get_plan(u,k,2);
67 }
68 }
69 void calc(int l,int r,int x,int y){
70 if (x==y){
71 for(int i=l;i<=r;i++)ans[a[i]]=v[x];
72 return;
73 }
74 sort(a+l,a+r+1,cmp1);
75 st[0]=0;
76 vv.clear();
77 ve.clear();
78 for(int j=l;j<=r;j++){
79 vv.push_back(a[j]);
80 if (!st[0]){
81 st[++st[0]]=a[j];
82 continue;
83 }
84 int k=lca(a[j],st[st[0]]);
85 while ((st[0]>1)&&(dep[k]==dep[lca(a[j],st[st[0]-1])])){
86 ve.push_back(make_pair(st[st[0]-1],st[st[0]]));
87 st[0]--;
88 }
89 if (st[st[0]]!=k){
90 vv.push_back(k);
91 ve.push_back(make_pair(k,st[st[0]]));
92 st[st[0]]=k;
93 }
94 st[++st[0]]=a[j];
95 }
96 for(int i=0;i<vv.size();i++){
97 e[0][vv[i]].clear(),e[1][vv[i]].clear();
98 vis[vv[i]]=f[vv[i]][0]=f[vv[i]][1]=0;
99 }
100 for(;st[0]>1;st[0]--)ve.push_back(make_pair(st[st[0]-1],st[st[0]]));
101 for(int i=0;i<ve.size();i++){
102 int xx=ve[i].first,yy=ve[i].second;
103 if (dep[xx]>=g[yy]){
104 e[las[yy]][xx].push_back(yy);
105 e[las[yy]^1][yy].push_back(xx);
106 }
107 }
108 int mid=(x+y>>1),tot=0;
109 for(int j=l;j<=r;j++){
110 if (a[j]==x0)tot++;
111 if (a[j]==y0)tot++;
112 }
113 if (tot<2){
114 for(int j=l;j<=r;j++){
115 f[a[j]][0]=1LL*abs(d[a[j]]-v[mid])*w[a[j]];
116 f[a[j]][1]=1LL*abs(d[a[j]]-v[mid+1])*w[a[j]];
117 }
118 for(int j=0;j<vv.size();j++)
119 if (!vis[vv[j]])dp(vv[j],0);
120 for(int j=0;j<vv.size();j++)vis[vv[j]]=0;
121 for(int j=0;j<vv.size();j++)
122 if (!vis[vv[j]])get_plan(vv[j],0,2);
123 }
124 else{
125 ll sum0=0,sum1=0;
126 for(int p=0;p<2;p++){
127 for(int j=l;j<=r;j++){
128 f[a[j]][0]=1LL*abs(d[a[j]]-v[mid])*w[a[j]];
129 f[a[j]][1]=1LL*abs(d[a[j]]-v[mid+1])*w[a[j]];
130 }
131 f[x0][p^1]=oo;
132 if (p)f[y0][0]=oo;
133 for(int j=0;j<vv.size();j++)
134 if (!vis[vv[j]]){
135 dp(vv[j],0);
136 if (!p)sum0+=min(f[vv[j]][0],f[vv[j]][1]);
137 else sum1+=min(f[vv[j]][0],f[vv[j]][1]);
138 }
139 for(int j=0;j<vv.size();j++)vis[vv[j]]=0;
140 }
141 if (sum0<sum1){
142 for(int j=l;j<=r;j++){
143 f[a[j]][0]=1LL*abs(d[a[j]]-v[mid])*w[a[j]];
144 f[a[j]][1]=1LL*abs(d[a[j]]-v[mid+1])*w[a[j]];
145 }
146 f[x0][1]=oo;
147 for(int j=0;j<vv.size();j++)
148 if (!vis[vv[j]])dp(vv[j],0);
149 for(int j=0;j<vv.size();j++)vis[vv[j]]=0;
150 }
151 for(int j=0;j<vv.size();j++)
152 if (!vis[vv[j]])get_plan(vv[j],0,2);
153 }
154 sort(a+l,a+r+1,cmp2);
155 for(int j=l;j<=r+1;j++)
156 if ((j>r)||(bl[a[j]])){
157 if (l<j)calc(l,j-1,x,mid);
158 if (j<=r)calc(j,r,mid+1,y);
159 return;
160 }
161 }
162 int main(){
163 scanf("%d%d",&n,&m);
164 for(int i=1;i<=n;i++)scanf("%d",&d[i]);
165 for(int i=1;i<=n;i++)scanf("%d",&w[i]);
166 for(int i=1;i<=n;i++)fa[i][0]=i;
167 for(int i=1;i<=m;i++){
168 scanf("%d%d",&x,&y);
169 if (find(x)==find(y))x0=x,y0=y;
170 else{
171 fa[x][0]=find(y);
172 e[0][x].push_back(y);
173 e[1][y].push_back(x);
174 }
175 }
176 x=0;
177 dfs(1,1,0);
178 memcpy(v,d,sizeof(v));
179 sort(v+1,v+n+1);
180 int nn=unique(v+1,v+n+1)-v-1;
181 for(int i=1;i<=n;i++)a[dfn[i]]=i;
182 calc(1,n,1,nn);
183 for(int i=1;i<=n;i++)sum+=1LL*w[i]*abs(d[i]-ans[i]);
184 printf("%lld",sum);
185 }
[loj2470]有向图的更多相关文章
- Kosaraju 算法检测有向图的强连通性
给定一个有向图 G = (V, E) ,对于任意一对顶点 u 和 v,有 u --> v 和 v --> u,亦即,顶点 u 和 v 是互相可达的,则说明该图 G 是强连通的(Strong ...
- POJ 2337 Catenyms(有向图的欧拉通路)
题意:给n个字符串(3<=n<=1000),当字符串str[i]的尾字符与str[j]的首字符一样时,可用dot连接.判断用所有字符串一次且仅一次,连接成一串.若可以,输出答案的最小字典序 ...
- 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 ...
- 有向图强连通分量的Tarjan算法
有向图强连通分量的Tarjan算法 [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G ...
- hdu1269迷宫城堡(判断有向图是否是一个强连通图)
1 /* 题意: 给你一个图,求这个有向图示否是一个强连通图(每两个节点都是可以相互到达的)! 思路1:按正向边dfs一遍,将经过的节点计数,如果记录的节点的个数小于n,那么就说明图按照正向边就不是连 ...
- poj 1386 Play on Words(有向图欧拉回路)
/* 题意:单词拼接,前一个单词的末尾字母和后一个单词的开头字母相同 思路:将一个单词的开头和末尾单词分别做两个点并建一条有向边!然后判断是否存在欧拉回路或者欧拉路 再次强调有向图欧拉路或欧拉回路的判 ...
- NYOJ 99单词拼接(有向图的欧拉(回)路)
/* NYOJ 99单词拼接: 思路:欧拉回路或者欧拉路的搜索! 注意:是有向图的!不要当成无向图,否则在在搜索之前的判断中因为判断有无导致不必要的搜索,以致TLE! 有向图的欧拉路:abs(In[i ...
- 邻接表有向图(三)之 Java详解
前面分别介绍了邻接表有向图的C和C++实现,本文通过Java实现邻接表有向图. 目录 1. 邻接表有向图的介绍 2. 邻接表有向图的代码说明 3. 邻接表有向图的完整源码 转载请注明出处:http:/ ...
- 邻接表有向图(二)之 C++详解
本章是通过C++实现邻接表有向图. 目录 1. 邻接表有向图的介绍 2. 邻接表有向图的代码说明 3. 邻接表有向图的完整源码 转载请注明出处:http://www.cnblogs.com/skywa ...
随机推荐
- 极简SpringBoot指南-Chapter02-Spring依赖注入的方式
仓库地址 w4ngzhen/springboot-simple-guide: This is a project that guides SpringBoot users to get started ...
- 无法解析的外部符号"void_cdecl caffe::caffe_gpu_dot<double>(int,double........)"
将源码中的.cu文件添加到项目中即可,即使创建的就是NVIDIA的项目,也需要把这些个.cu文件添加进来
- Go语言核心36讲(Go语言基础知识四)--学习笔记
04 | 程序实体的那些事儿(上) 还记得吗?Go 语言中的程序实体包括变量.常量.函数.结构体和接口. Go 语言是静态类型的编程语言,所以我们在声明变量或常量的时候,都需要指定它们的类型,或者给予 ...
- 洛谷4035 JSOI2008球形空间产生器 (列柿子+高斯消元)
题目链接 qwq 首先看到这个题,感觉就应该从列方程入手. 我们设给定的点的坐标矩阵是\(x\),然后球心坐标\(a_1,a_2....a_n\) 根据欧几里得距离公式,对于一个\(n维空间\)的第\ ...
- 如何接入 K8s 持久化存储?K8s CSI 实现机制浅析
作者 王成,腾讯云研发工程师,Kubernetes contributor,从事数据库产品容器化.资源管控等工作,关注 Kubernetes.Go.云原生领域. 概述 进入 K8s 的世界,会发现有很 ...
- 大牛针对零基础入门c语言详解指针(超详细)
C语言指针说难不难但是说容易又是最容易出错的地方,因此不管是你要做什么只要用到C指针你就跳不过,今天咱们就以 十九个例子来给大家简单的分析一下指针的应用,最后会有C语言视频资料提供给大家更加深入的参考 ...
- 最近公共祖先 牛客网 程序员面试金典 C++ Python
最近公共祖先 牛客网 程序员面试金典 C++ Python 题目描述 有一棵无穷大的满二叉树,其结点按根结点一层一层地从左往右依次编号,根结点编号为1.现在有两个结点a,b.请设计一个算法,求出a和b ...
- 第09课 OpenGL 移动图像
3D空间中移动图像: 你想知道如何在3D空间中移动物体,你想知道如何在屏幕上绘制一个图像,而让图像的背景色变为透明,你希望有一个简单的动画.这一课将教会你所有的一切.前面的课程涵盖了基础的OpenGL ...
- kafaka高效吞吐量-生产端,服务端,消费端
零拷贝:sendfile 生产端 生产端:消息压缩,缓存批量发送,异步解耦 多线程并发:防止某一个业务阻塞等待 接收消息缓存 BufferPool设计:不释放 服务端 Reactor模型,顺序写,页缓 ...
- Java测试开发--JSONPath、JSONArray、JSONObject使用(十)
一.Maven项目,pom.xml文件中导入 <dependency> <groupId>com.alibaba</groupId> <artifactId& ...