比赛 |
近期练习题回顾 |
评测结果 |
AAAAAAAAAAAAAAAAAAAA |
题目名称 |
运输计划 |
最终得分 |
100 |
用户昵称 |
liuyu |
运行时间 |
3.499 s |
代码语言 |
C++ |
内存使用 |
42.27 MiB |
提交时间 |
2018-10-29 16:44:31 |
显示代码纯文本
#include<bits/stdc++.h>
#define ll long long
#define lc o<<1,l,mid
#define rc o<<1|1,mid+1,r
using namespace std;
inline void in(int &x){
x=0;char c=getchar();
while(!isdigit(c))c=getchar();
while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();
}
const int N=300000+10;
const int INF=(1<<30)-1+(1<<30);
int n,m,a,b,w;
struct edg{int to,w;};
vector<edg>v[N];//存图
int dist[N];//放点上的边权
int cud[N<<2];//不经过次边的最长链的长度
int sum[N<<2];//链长和
edg lr[N];//链对应的在dfs序中的区间
int llr;//区间个数
int ans=2e9;//最终结果(最大值最小)
int mx,my,maxl=0,lca;//最长链的x,y,长度l
int s,t,x,y,su=0,nowl,bui=0;
int dfn[N],size[N],pos[N],top[N],son[N],eend[N],fa[N],deep[N];
void dfs1(int x);
void dfs2(int x,int root);
void init();
void build(int o,int l,int r);
void que(int o,int l,int r);
void que1(int o,int l,int r,int MAX);
void update(int o,int l,int r);
bool cmp(edg a,edg b){return a.to <b.to ;}
int main(){
freopen("transport.in","r",stdin);
freopen("transport.out","w",stdout);
init();
for(int i=1;i<=m;i++){
in(x),in(y);//先求出链的长度、所有区间,再更新区间补集
nowl=0;llr=0;
int fx=top[x],fy=top[y],a=x,b=y,llc;
while(fx!=fy){
if(deep[fx]>=deep[fy])
s=pos[fx],t=pos[x],que(1,1,n),x=fa[fx],lr[++llr].to=s,lr[llr].w=t;
else s=pos[fy],t=pos[y],que(1,1,n),y=fa[fy],lr[++llr].to=s,lr[llr].w=t;
fx=top[x],fy=top[y];//cout<<"====="<<nowl<<" "<<x<<" "<<y<<endl;
}
if(x!=y){
if(pos[x]>pos[y])swap(x,y);
s=pos[x]+1,t=pos[y];que(1,1,n);//cout<<x<<" "<<y<<" "<<s<<" "<<t<<" "<<i<<" "<<nowl<<endl;
lr[++llr].to=s,lr[llr].w=t;
}llc=x;
if(nowl>maxl)maxl=nowl,mx=a,my=b,lca=llc;
s=1;
//cout<<a<<" "<<b<<" "<<nowl<<" "<<lca<<endl;
sort(lr+1,lr+llr+1,cmp);
for(int j=1;j<=llr;j++){
if(j==1){
if(lr[j].to==1)continue;
else t=lr[j].to-1;
}else s=lr[j-1].w+1,t=lr[j].to-1;
if(s>t)continue;
else update(1,1,n);
}
if(lr[llr].w<n)s=lr[llr].w+1,t=n,update(1,1,n);
}
while(mx!=lca){
nowl=0;s=pos[mx];que1(1,1,n,0);//cout<<mx<<"---mXXXX: "<<nowl<<" "<<maxl-dist[my]<<endl;
ans=min(ans,max(maxl-dist[mx],nowl));
mx=fa[mx];
}while(my!=lca){
nowl=0;s=pos[my];que1(1,1,n,0);//cout<<my<<"---mYYYY: "<<nowl<<" "<<maxl-dist[my]<<endl;
ans=min(ans,max(maxl-dist[my],nowl));
my=fa[my];
}
cout<<ans<<endl;
//for(int i=1;i<=n;i++)cout<<i<<" "<<pos[i]<<endl;
return 0;
}
void build(int o,int l,int r){
if(l==r)sum[o]=dist[dfn[++bui]];
else{
int mid=(l+r)>>1;
build(lc),build(rc);
sum[o]=sum[o<<1]+sum[o<<1|1];
}
}
void que(int o,int l,int r){//nowl
if(s<=l&&r<=t)nowl+=sum[o];
else{
int mid=(l+r)>>1;
if(s<=mid)que(lc);
if(t>mid)que(rc);
}
}
void update(int o,int l,int r){
if(s<=l&&r<=t)cud[o]=max(cud[o],nowl);
else{
int mid=(l+r)>>1;
if(s<=mid)update(lc);
if(t>mid)update(rc);
//cud[o]=max(cud[o],max(cud[o<<1],cud[o<<1|1]));
}
}
void que1(int o,int l,int r,int MAX){
if(l==r)nowl=max(cud[o],MAX);
else{
int mid=(l+r)>>1;
if(s<=mid)que1(lc,max(MAX,cud[o]));
else que1(rc,max(MAX,cud[o]));
}
}
void init(){
in(n),in(m);
for(int i=1;i<n;i++){
in(a),in(b),in(w);
v[a].push_back((edg){b,w});
v[b].push_back((edg){a,w});
}
//size[]son[]deep[]fa[]
deep[1]=1;fa[1]=1;
dfs1(1);
//dfn[]top[]eend[]
dfn[++su]=1;
top[1]=1;
dfs2(1,1);
for(int i=1;i<=su;i++)pos[dfn[i]]=i;
build(1,1,n);
}
void dfs1(int x){//size[]son[]deep[]fa[]
int maxsize=0;
if(v[x].size()==1&&x!=1){size[x]=1;return;}
size[x]=1;
for(int i=0;i<v[x].size();i++){
edg e=v[x][i];
if(fa[x]!=e.to){
deep[e.to]=deep[x]+1;
fa[e.to]=x;
dist[e.to]=e.w;
dfs1(e.to);
size[x]+=size[e.to];
if(size[e.to]>maxsize)
maxsize=size[e.to],
son[x]=e.to;
}
}
}
void dfs2(int x,int root){//dfn[]top[]eend[]
int f=1;
if(son[x]){
f=0;
dfn[++su]=son[x];
top[son[x]]=root;
dfs2(son[x],root);
}
for(int i=0;i<v[x].size();i++){
edg e=v[x][i];
if(fa[x]!=e.to&&e.to!=son[x]){
if(f)top[e.to]=root,f=0;
else top[e.to]=e.to;
dfn[++su]=e.to;
dfs2(e.to,e.to);
}
}
eend[x]=su;
}
/*
6 3
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5
*/