zoukankan      html  css  js  c++  java
  • 运输计划

    洛咕

    分析:题目要求删去一条边后最长路径最短,显然是要二分答案.假设当前二分了最长路径长度为(mid),那么(m)条路径中,所有长度大于(mid)的路径,都要删去它们的最长的公共边.这条公共边要怎么求?树上差分---边差分.如果减去这条最长公共边之后所有的路径长度都小于等于(mid),就说明二分合法.

    这题其实有思路的话,还是很好写的.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=3e5+5;
    int n,m,x[N],y[N],z[N],lca[N],dep[N];
    int f[N][21],d[N][21],cnt[N];
    int tot,head[N],nxt[N<<1],to[N<<1],w[N<<1];
    inline void add(int a,int b,int c){
    	nxt[++tot]=head[a];head[a]=tot;to[tot]=b;w[tot]=c;
    }
    inline void dfs(int u,int fa){
    	for(int j=1;j<=20;++j){
    		f[u][j]=f[f[u][j-1]][j-1];
    		d[u][j]=d[u][j-1]+d[f[u][j-1]][j-1];
    	}
    	for(int i=head[u];i;i=nxt[i]){
    		int v=to[i];if(v==fa)continue;
    		dep[v]=dep[u]+1;f[v][0]=u;d[v][0]=w[i];
    		dfs(v,u);
    	}
    }
    inline int LCA(int x,int y){
    	if(dep[x]<dep[y])swap(x,y);
    	for(int j=20;j>=0;--j)if(dep[f[x][j]]>=dep[y])x=f[x][j];
    	if(x==y)return x;
    	for(int j=20;j>=0;--j)if(f[x][j]!=f[y][j])x=f[x][j],y=f[y][j];
    	return f[x][0];
    }
    inline void dp(int u,int fa){
    	for(int i=head[u];i;i=nxt[i]){
    		int v=to[i];if(v==fa)continue;
    		dp(v,u);cnt[u]+=cnt[v];
    	}
    }
    inline bool check(int mid){
    	for(int i=0;i<=n;++i)cnt[i]=0;
    	int num=0;
    	for(int i=1;i<=m;++i){
    		if(z[i]<=mid)continue;
    		++cnt[x[i]];++cnt[y[i]];cnt[lca[i]]-=2;
    		++num;
    	}
    	if(!num)return 1;
    	dp(1,0);int maxn=0;
    	for(int i=1;i<=n;++i)
    		if(cnt[i]==num){
    			maxn=max(maxn,d[i][0]);
    		}
    	if(!maxn)return 0;
    	for(int i=1;i<=m;++i)if(z[i]-maxn>mid)return 0;
    	return 1;
    }
    int main(){
    	n=read();m=read();
    	for(int i=1;i<n;++i){
    		int a=read(),b=read(),c=read();
    		add(a,b,c);add(b,a,c);
    	}
    	dep[1]=1;f[1][0]=1;dfs(1,0);
    	for(int i=1;i<=m;++i){
    		x[i]=read();y[i]=read();
    		lca[i]=LCA(x[i],y[i]);
    		int nowx=x[i],nowy=y[i];
    		int k1=dep[x[i]]-dep[lca[i]],k2=dep[y[i]]-dep[lca[i]];
    		for(int j=20;j>=0;--j){
    			if(k1&(1<<j)){
    				z[i]+=d[nowx][j];
    				nowx=f[nowx][j];
    			}
    			if(k2&(1<<j)){
    				z[i]+=d[nowy][j];
    				nowy=f[nowy][j];
    			}
    		}
    	}
    	int l=0,r=1e9,mid,ans=0;
    	while(l<=r){
    		mid=(l+r)>>1;
    		if(check(mid))ans=mid,r=mid-1;
    		else l=mid+1;
    	}
    	printf("%d
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    你知道怎么离线安装全局 node 模块吗?
    关于开发视图
    你知道 JavaScript 中的 Arguments 对象都有哪些用途吗?
    前端 JavaScript 实现一个简易计算器
    Docker 系列 _ 01_ 一念缘起
    机器学习资料大全
    pdf、txt文本复制到EXCEL后的格式快速调整法
    习惯的养成
    磁盘剩余空间监控
    please wait while windows configures microsoft visual studio professional 2013
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11853540.html
Copyright © 2011-2022 走看看