【洛谷P2680】运输计划

题目链接

题目大意:

一棵\(n\)个点的带边权的数,给定\(m\)条树上两点间的路径,现在你可以让树上任意一条边的权值变为零,

问如何选边使得\(m\)条路径中边权和最大的路径的边权和最小

\(\mathcal{solution}\)

这是\(NOIP2015\)\(Day2T3\),感觉难度是比较大的

我首先想到的是,要选的边一定在边权和最大的路径上

于是我们可以先用\(lca\)找出边权和最大的路径的起始点,复杂度\(O(mlogn)\)

然后一遍\(dfs\)找出这个路径上所有的边,复杂度\(O(n)\)

之后枚举这个路径上的边,将它置为零,再重新\(dfs\)更新\(f\)数组,

然后枚举每条路径,求每条路径的权值和

复杂度\(O(n(n+mlogn))\),只有\(40\)

对于\(m=1\)的情况,我们可以直接一遍\(dfsO(n)\)解决

这样就有\(50\)分了

\(50\)分代码:

#include<iostream>
#include<cstring>
#include<cstdio> 
#define N 300010using namespace std;
const int INF=0x3f3f3f3f;inline int read(){int x=0; char c=getchar();while(c<'0')c=getchar();while(c>='0') x=(x<<3)+(x<<1)+c-'0',c=getchar();return x;
}int n,m,Head[N],num=1;
struct NODE{int to,w,next;
} e[N<<1];
inline void add(int x,int y,int w){e[++num].to=y;e[num].w=w;e[num].next=Head[x];Head[x]=num;
}
struct Data{    //路径的起始点int x,y;
} a[N];int f[N][25],sum[N][25],dep[N];
void dfs(int now,int fa){ f[now][0]=fa;dep[now]=dep[fa]+1;for(int i=1;(1<<i)<=dep[now];++i){f[now][i]=f[f[now][i-1]][i-1];sum[now][i]=sum[now][i-1]+sum[f[now][i-1]][i-1];}for(int i=Head[now];i;i=e[i].next)if(e[i].to!=fa){sum[e[i].to][0]=e[i].w;dfs(e[i].to,now);}
}inline int Get_Sum(int x,int y){        //lca求边权和int Sum=0;if(dep[x]!=dep[y]){if(dep[x]<dep[y]) swap(x,y);for(int i=20;i>=0&&dep[x]>dep[y];--i)if(dep[f[x][i]]>=dep[y])Sum+=sum[x][i],x=f[x][i];}if(x==y) return Sum;for(int i=20;i>=0;--i)if(f[x][i]!=f[y][i]){Sum+=sum[x][i]+sum[y][i];x=f[x][i],y=f[y][i];}return Sum+sum[x][0]+sum[y][0];
}int path[N],cnt;
bool dfs1(int now,int fa,int gl){        //已知起、始点,找出整条路径if(now==gl) return 1;for(int i=Head[now];i;i=e[i].next){int v=e[i].to;if(v==fa) continue;path[++cnt]=i;if(dfs1(v,now,gl)) return 1;--cnt;}return 0;
}int main()
{n=read(),m=read();int x,y,w;for(int i=1;i<n;++i){x=read(),y=read(),w=read();add(x,y,w),add(y,x,w);}for(int i=1;i<=m;++i)a[i].x=read(),a[i].y=read();if(m==1){dfs1(a[1].x,0,a[1].y);int max2=0,sum2=0;for(int i=1;i<=cnt;++i)sum2+=e[path[i]].w,max2=max(max2,e[path[i]].w);printf("%d\n",sum2-max2);return 0;}dfs(1,0);int k=0,maxx=0;for(int i=1;i<=m;++i){int t=Get_Sum(a[i].x,a[i].y);if(t>maxx) maxx=t,k=i;}int minn=INF;dfs1(a[k].x,0,a[k].y);for(int i=1;i<=cnt;++i){int k=path[i];int temp=e[k].w;e[k].w=e[k^1].w=0;dfs(1,0);e[k].w=e[k^1].w=temp;int maxx=0;for(int j=1;j<=m;++j)maxx=max(maxx,Get_Sum(a[j].x,a[j].y));minn=min(minn,maxx);}printf("%d\n",minn);return 0;
}

我们考虑如何搞到\(100\)

我们回到刚才的“题目大意”上来

问如何选边使得\(m\)条路径中\(\color{red}{边权和最大的路径的边权和最小}\)

这就提示我们要二分答案

我们考虑二分一个答案\(mid\)表示最小的最大路径边权和

如何判断呢?

我们可以发现,最终被我们置为零的边 一定被 所有的一开始边权和大于\(mid\)的路径 覆盖了一遍

而当满足上面条件时,边权和最大的路径减去这条边的长度\(\leq mid\),那么这个\(mid\)就是可以满足的

我们可以用树上差分来求哪条边被所有一开始不满足条件的路径覆盖了,如果不存在这样的边,说明不存在方案满足当前\(mid\)

总的复杂度是\(O(mlogn+(m+n)logSum_{max})\)

然而最后一个点(\(luogu\)\(\#13\))十分毒瘤,需要各种卡常(好歹没爆栈(雾

\(100\)分代码:

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio> 
#define N 300010
#define root (20181111%n+1)
#define re   
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")//#define swap(a,b) (a^=b^=a^=b)inline int Max(int a, int b){int diff=b-a;return b-(diff&(diff>>31));
}const int INF=0x3f3f3f3f,ch_top=4e7+3;
char ch[ch_top],*now_r=ch-1;inline int read(){while(*++now_r<'0');re int x=*now_r-'0';while(*++now_r>='0') x=(x<<3)+(x<<1)+*now_r-'0';return x;
}int n,m,Head[N],num=1,mid,ha;
struct NODE{int to,w,next;
} e[N<<1];
struct Data{int x,y,sum,lca;
} a[N];int f[N][25],sum[N][25],dep[N],Max_sum;
inline void dfs(int now,int fa){f[now][0]=fa; dep[now]=dep[fa]+1;for(re int i=1;(1<<i)<=dep[now];++i){f[now][i]=f[f[now][i-1]][i-1];sum[now][i]=sum[now][i-1]+sum[f[now][i-1]][i-1];}for(re int i=Head[now],v=e[i].to;i;i=e[i].next,v=e[i].to)if(v!=fa)sum[v][0]=e[i].w,dfs(v,now);
}inline void Get_Lca(int p){int Sum=0,x=a[p].x,y=a[p].y;if(dep[x]!=dep[y]){if(dep[x]<dep[y]) x^=y^=x^=y;for(re int i=19;dep[x]>dep[y];--i)if(dep[f[x][i]]>=dep[y]){Sum+=sum[x][i];x=f[x][i];}}if(x==y){a[p].sum=Sum;a[p].lca=x;return;}for(re int i=19;i>=0;--i)if(f[x][i]!=f[y][i]){Sum+=sum[x][i]+sum[y][i];x=f[x][i]; y=f[y][i];}a[p].sum=Sum+sum[x][0]+sum[y][0];a[p].lca=f[x][0];
}int diff[N];bool dfs1(int now,int len,int fa){int tot=diff[now];for(re int i=Head[now],v=e[i].to;i;i=e[i].next,v=e[i].to)if(v!=fa){if(dfs1(v,e[i].w,now)) return 1;tot+=diff[v];}diff[now]=tot;if(tot==ha&&Max_sum-len<=mid)return 1;return 0;
}inline bool check(){ha=0;memset(diff,0,sizeof(diff));for(re int i=1;i<=m;++i)if(a[i].sum>mid){++ha;++diff[a[i].x],++diff[a[i].y];diff[a[i].lca]-=2;}return dfs1(root,0,0);
}int main()
{
//  freopen("a.in","r",stdin);  
//  int size = 256 << 20; //250M
//    char*p=(char*)malloc(size) + size;
//    __asm__("movl %0, %%esp\n" :: "r"(p) );fread(ch,1,ch_top,stdin);n=read(),m=read();int x,y,w;for(re int i=1;i<n;++i){x=read(),y=read(),w=read();e[++num].to=y;e[num].w=w;e[num].next=Head[x];Head[x]=num;e[++num].to=x;e[num].w=w;e[num].next=Head[y];Head[y]=num;}dfs(root,0);for(re int i=1;i<=m;++i){a[i].x=read(),a[i].y=read();Get_Lca(i);Max_sum=Max(Max_sum,a[i].sum);}re int l(0),r=Max_sum;while(l<r){mid=(l+r)>>1;if(check()) r=mid;else l=mid+1;}printf("%d\n",l);return 0;
}

转载于:https://www.cnblogs.com/yjkhhh/p/9915472.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/265527.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu下软件的安装、卸载方法

参考&#xff1a;Ubuntu 如何使用命令卸载安装过的软件&#xff08;超级简单&#xff09; 作者&#xff1a;一只青木呀 发布时间&#xff1a;2020-08-04 09:19:01 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/107778981 参考&#xff1a;Ubuntu下软…

webservice系统学习笔记9-使用契约优先的方式的一个服务端demo(隐式传Header信息)...

服务器端&#xff1a; 1、编写wsdl文件 <?xml version"1.0" encoding"UTF-8" standalone"no"?> <wsdl:definitions xmlns:soap"http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns"http://www.example.org/mywsdl/&qu…

java gzip 多个文件_Java Zip多文件压缩和 GZIP压缩

/*** 多文件压缩** author Administrator**/public class ZipCompress {public static void main(String args[]) {String[] filepaths { "D:\\zip1.txt", "D:\\zip2.txt" };try {FileOutputStream f new FileOutputStream("D://test.zip");//…

Ubuntu文件压缩、解压缩、打包解包(带软链接)、拷贝文件(带软链接)、拷贝文件夹

参考&#xff1a;Ubuntu 命令解压文件大全 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-08-04 17:18:55 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/107791294 参考&#xff1a;打包和压缩的概念和区别 作者&#xff1a;不浪漫的罪名L…

java 内存和实际内存_请问更改eclipse内存和更改jvm内存是一会事儿吗?

RSS列 表示&#xff0c; 程序占用了多少物理内存。 虚拟内存可以不用考虑&#xff0c;它并不占用实际物理内存。 (2). top 命令也可以 其中VIRT(或VSS)列 表示&#xff0c;程序占用了多少虚拟内存。 同 ps aux 中的 VSZ列 RES列 表示&#xff0c; 程序占用了多少物理内存。同 p…

thinkphp 编辑器kindeditor

首先&#xff0c;去官网下载最新版的kindeditor&#xff0c;然后把里面asp&#xff0c;jsp&#xff0c;net&#xff0c;example的全删除&#xff0c;然后改名为editor放进public&#xff08;最外层目录的public&#xff09;文件夹里面 在目录lib目录建立ORG文件夹&#xff08;个…

equation

equation 题目描述 有一棵n 个点的以 1 为根的树, 以及 n 个整数变量xi。树上 i 的父亲是 fi&#xff0c; 每条边(i,fi)有一个权值wi&#xff0c;表示一个方程 xi xfi wi&#xff0c;这 n-1个方程构成了一个方程组。 现在给出q 个操作&#xff0c;有两种类型: 1 u v s&#x…

Ubuntu开启FTP服务方法(Ubuntu和Windows之间互传文件需要开启——服务器端)

目录Ubuntu开启FTP服务步骤&#xff1a;Ubuntu开启FTP服务步骤&#xff1a; 工作中Ubuntu和Windows之间互传文件&#xff0c;需要服务器端&#xff08;Ubuntu&#xff09;开启FTP服务&#xff0c;客户端&#xff08;Windows&#xff09;安装FileZilla。平时自己学习电脑安装虚拟…

舞伴配对问题java_舞伴配对问题

循环队列的应用——舞伴配对问题&#xff1a;在舞会上&#xff0c;男、女各自排成一队。舞会开始时&#xff0c;依次从男队和女队的队头各出一人配成舞伴。如果两队初始人数不等&#xff0c;则较长的那一队中未配对者等待下一轮舞曲。假设初始男、女人数及性别已经固定&#xf…

逆元

复习逆元…… 逆元 求法&#xff1a; 1&#xff0c;快速幂     根据费马小定理有\(a^{p - 1} \equiv 1 \quad (mod \quad p)\),把左边拆开一下得到     \[a \cdot a^{p - 2} \equiv 1 \quad (mod \quad p)\]     因此\(a^{p - 2}\)为\(a\)在\(mod \quad p\)意义下的…

java如何让线程等待_如何使Java线程等待另一个线程的输出?

我真的建议你经历一个教程&#xff0c;如Sun’s Java Concurrency&#xff0c;你开始在多线程的魔法世界。还有一些好书出来了(google for“Concurrent Programming in Java”&#xff0c;“Java Concurrency in Practice”)。要得到你的答案&#xff1a;在你必须等待dbThread的…

win7共享wifi

为什么80%的码农都做不了架构师&#xff1f;>>> 1.从开始菜单找到“命令提示符”&#xff0c;或直接键入cmd快速搜索&#xff0c;右键单击它&#xff0c;选择“以管理员身份运行” 2.运行以下命令启用虚拟无线网卡&#xff1a; netsh wlan set hostednetwork mod…

Ubuntu开启NFS、SSH服务(驱动开发用到、电脑端登录ARM板用到)

参考&#xff1a;Ubuntu下NFS服务的开启 作者&#xff1a;一只青木呀 发布时间&#xff1a;2020-08-04 14:06:58 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/107784877 目录NFS服务的开启1.安装NFS服务2.创建 linux 工作目录3.配置NFSUbuntu下SSH…

【整理】MySQL 之 autocommit

2019独角兽企业重金招聘Python工程师标准>>> mysql 默认是开启 auto commit 的。可以通过如下命令查看 session 级别和 global 级别的设置&#xff1a; mysql> select session.autocommit; ---------------------- | session.autocommit | ---------------------…

java某个类避免findbug检查_Findbugs能否在java中检测到捕获RuntimeException?

你能不能让我知道Findbugs可以在java中检测到catcing RuntimeException吗&#xff1f;有效的java建议我们不要捕获RuntimeException.所以我想知道Findbugs可以抓错了.另外,我已经检查过Klocwork JD.CATCH和checkstyle IllegalCatch是否适用于此目的.最佳答案 有点.在findbugs中…

交叉编译链的安装

参考&#xff1a;嵌入式 交叉编译链的安装 作者&#xff1a;一只青木呀 发布时间&#xff1a;2020-08-04 18:13:13 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/107789879 目录什么是交叉编译器交叉编译器的下载交叉编译器的安装1.把下载的文件放到…

Scrapy将爬取的段落整合为字符串

使用Scrapy框架爬取文章的时候&#xff0c;经常会遇到要爬取多个段落的问题&#xff0c;如果这个时候使用的是&#xff1a; text response.xpath("......").extract() 那么会发现爬取下来的文章是以段落为单位的list&#xff0c;不方便直接展示。 这个时候可以将lis…

Ubuntu下安装VS Code以及C/C++插件(PS工作目录的创建)

参考&#xff1a;Visual Studio Code Ubuntu下安装 以及C/C插件大全 作者&#xff1a;一只青木呀 发布时间&#xff1a;2020-08-05 11:55:53 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/107811506 目录为何选择安装VS CodeVisual Studio Code 安装…

Common Lisp中调用R

2019独角兽企业重金招聘Python工程师标准>>> R是功能强大的统计软件&#xff0c;和Lisp一样也有一个交互式的命令行环境&#xff0c;还有众多的扩展库&#xff0c;可以用来进行专业的统计分析。要在Common Lisp中方便的调用R的功能&#xff0c;可以试用rcl这个库。安…

java生成pdf加密_java使用iText 生成PDF全攻略(表格,加密)

java使用iText 生成PDF全攻略,包括创建文档,设置字体,添加表格(PdfPTable),创建新页(newPage),设置布局,加密主要使用的jar包: itextpdf-5.4.2.jar,itext-pdfa-5.4.2.jar,itext-xtra-5.4.2.jar,如果用到中文&#xff0c;需要CJK字体的扩展包&#xff1a;itext-asian.jar如果用到…