博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NOIP2015 运输计划 二分答案+Tarjan LCA+树上差分
阅读量:5859 次
发布时间:2019-06-19

本文共 3005 字,大约阅读时间需要 10 分钟。

题目描述

需要的最短时间,明显二分

判断答案是否可行只要把超过答案的路径都记下来,找到一条所有超过的答案路径都经过的边,尝试删掉它,如果最长的路减去它小于答案,那么此答案就是可行的解
至于统计所有路径都经过的边,统计一下就好

经过running的折磨,感觉transport突然变简单了

代码

#include
#include
#include
#include
#include
using namespace std;const int N=300010;int n, m, lca[N], a[N], b[N];int he[N], ne, hq[N], nq, rt;struct E {
int to, next, w;} e[N<<1];void build (int u, int v, int w) {e[ne]=(E){v,he[u],w}; he[u]=ne++; e[ne]=(E){u,he[v],w}; he[v]=ne++;}struct Q{
int to, next, flag, idx;} q[N<<1];void add(int u, int v, int m) {q[nq]=(Q){v,hq[u],0,m}; hq[u]=nq++; q[nq]=(Q){u,hq[v],0,m}; hq[v]=nq++;}int f[N],vis[N],dep[N],dis[N],pre[N];int find(int v) {
return v == f[v] ? v : f[v]=find(f[v]);}void tarjan (int u, int fa){ int v; vis[u]=1; dep[u]=dep[fa]+1; f[u]=u; for(int i=he[u]; i != -1; i=e[i].next) { if((v=e[i].to) == fa) continue; dis[v]=dis[u]+e[i].w; pre[v]=e[i].w; //printf("%d %d %d\n",v,dis[u],dis[v]); tarjan(v, u); f[v]=u; } for(int i=hq[u]; i != -1; i=q[i].next) { if(!vis[v=q[i].to] || q[i].flag) continue; q[i].flag=q[i^1].flag=1; lca[q[i].idx]=find(v); //printf("%d %d\n",q[i].idx,lca[q[i].idx]); }}int len[N],mark[N],maxm;void pushup(int u, int fa){ int v; for(int i=he[u]; i != -1; i=e[i].next) { if((v=e[i].to) == fa) continue; pushup(v,u); mark[u]+=mark[v]; }}int check(int k){ memset(mark,0,sizeof(mark)); int cnt=0; for(int i=1; i <= m; i++) if(len[i] > k) { cnt++; mark[a[i]]++,mark[b[i]]++,mark[lca[i]]-=2; } pushup(rt,0); for(int i=1; i <= n; i++) if(maxm-pre[i] <= k && mark[i] == cnt) return 1; return 0;}void solve(){ tarjan(rt,0);int r=0,l=0; for(int i=1; i<= m; i++) { len[i]=dis[a[i]]+dis[b[i]]-(dis[lca[i]]<<1); if(len[i] > r) maxm=r=len[i]; } int ans; while(l <= r) { int mid=(l+r)>>1; if(check(mid)) r=mid-1,ans=mid; else l=mid+1; } printf("%d\n",ans);}int read(){ int out=0;char c=getchar();while(c > '9' || c < '0') c=getchar(); while(c >= '0' && c <= '9') {out=(out<<1)+(out<<3)+c-'0';c=getchar();} return out;}int siz[N],mind=N;void dfs(int u, int fa){ siz[u]=1; int minn=N,maxn=-N,v; for(int i=he[u]; i != -1; i=e[i].next) { if((v=e[i].to) == fa) continue; dfs(v,u); siz[u]+=siz[v]; if(minn > siz[v]) minn=siz[v]; } if(minn == N) return ; if(minn > n-siz[u] && fa) minn=n-siz[u]; if(maxn < n-siz[u]) maxn=n-siz[u]; if(maxn-minn < mind) rt=u,mind=maxn-minn;}void init(){ memset(he,-1,sizeof(he));memset(hq,-1,sizeof(hq)); n=read(),m=read();int u,v,w; for(int i=1; i < n; i++) u=read(),v=read(),w=read(),build(u,v,w); for(int i=1; i <= m; i++) a[i]=read(),b[i]=read(),add(a[i],b[i],i); dfs(1,0);}int main(){ init();solve(); return 0;}

转载于:https://www.cnblogs.com/zerolt/p/9260892.html

你可能感兴趣的文章
TypeScript语言特性(下)
查看>>
日交易笔百万级,Ping++的大数据平台架构
查看>>
手机及电脑抓包(tcp,udp,http)
查看>>
数据结构例程——表达式求值(用栈结构)
查看>>
5项优化4种高可用方案,MySQL常用架构调优这样做!
查看>>
携程网基于应用的自动化容量管理与评估
查看>>
如何解决数据库分词的拼写纠正问题 - PostgreSQL Hunspell 字典 复数形容词动词等变异还原...
查看>>
java中的mvc和三层结构究竟是什么关系
查看>>
【阿里招聘】一位阿里实习生的忏悔:假如回到大学
查看>>
Java序列化和反序列化
查看>>
当物流行业遇见MongoDB
查看>>
Hadoop Namenode不能启动 dfs/name is in an inconsistent
查看>>
Linux_指令杂烩
查看>>
Python 利用pexpect和paramiko模块进行远程服务器的监控
查看>>
【IOS-COCOS2D游戏开发之九】讲解CCSPRITEBATCHNODE与TP工具的”.PVR.CCZ”,”.PLIST”共用的终极精灵优化及注意事项!...
查看>>
如何通过云存储实现大文件的断点下载和上传
查看>>
[NHibernate]HQL查询
查看>>
weex中使用数据流工具Vuex实践
查看>>
深入Log4J源码之Layout
查看>>
搭建一个免费的,无限流量的Blog----github Pages和Jekyll入门
查看>>