• 【BZOJ4890】[TJOI2017]城市(动态规划)


    【BZOJ4890】[TJOI2017]城市(动态规划)

    题面

    BZOJ
    洛谷

    题解

    数据范围都这样了,显然可以暴力枚举断开哪条边。
    然后求出两侧直径,暴力在直径上面找到一个点,使得其距离直径两端点的最大距离最小。
    然后我用线段树求的直径,就跑得很快了。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define ll long long
    #define MAX 5050
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int n;
    struct Line{int v,next,w;}e[MAX<<1];
    int h[MAX],cnt=1;
    inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;}
    int size[MAX],hson[MAX],dfn[MAX],low[MAX],tim,top[MAX],dep[MAX],fa[MAX],dis[MAX],ln[MAX];
    void dfs1(int u,int ff)
    {
    	fa[u]=ff;size[u]=1;dep[u]=dep[ff]+1;
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;if(v==ff)continue;
    		dis[v]=dis[u]+e[i].w;dfs1(v,u);size[u]+=size[v];
    		if(size[v]>size[hson[u]])hson[u]=v;
    	}
    }
    void dfs2(int u,int tp)
    {
    	top[u]=tp;dfn[u]=++tim;ln[tim]=u;
    	if(hson[u])dfs2(hson[u],tp);
    	for(int i=h[u];i;i=e[i].next)
    		if(e[i].v!=fa[u]&&e[i].v!=hson[u])
    			dfs2(e[i].v,e[i].v);
    	low[u]=tim;
    }
    int LCA(int u,int v)
    {
    	while(top[u]^top[v])dep[top[u]]<dep[top[v]]?v=fa[top[v]]:u=fa[top[u]];
    	return dep[u]<dep[v]?u:v;
    }
    int Dis(int u,int v){return dis[u]+dis[v]-2*dis[LCA(u,v)];}
    struct Node{int u,v;}t[MAX<<2];
    Node operator+(Node a,Node b)
    {
    	Node tmp[6];int nd=Dis(a.u,a.v);
    	tmp[0]=a;tmp[1]=b;tmp[2]=(Node){a.u,b.u};tmp[3]=(Node){a.u,b.v};
    	tmp[4]=(Node){a.v,b.u};tmp[5]=(Node){a.v,b.v};
    	for(int i=1;i<6;++i)
    	{
    		int x=Dis(tmp[i].u,tmp[i].v);
    		if(x>nd)nd=x,swap(tmp[0],tmp[i]);
    	}
    	return tmp[0];
    }
    #define lson (now<<1)
    #define rson (now<<1|1)
    void Build(int now,int l,int r)
    {
    	if(l==r){t[now]=(Node){ln[l],ln[l]};return;}
    	int mid=(l+r)>>1;
    	Build(lson,l,mid);Build(rson,mid+1,r);
    	t[now]=t[lson]+t[rson];
    }
    Node Query(int now,int l,int r,int L,int R)
    {
    	if(L==l&&r==R)return t[now];
    	int mid=(l+r)>>1;
    	if(R<=mid)return Query(lson,l,mid,L,R);
    	if(L>mid)return Query(rson,mid+1,r,L,R);
    	return Query(lson,l,mid,L,mid)+Query(rson,mid+1,r,mid+1,R);
    }
    int ans=1e9;
    int Brute(int u,int v)
    {
    	vector<int> a,b;int w=LCA(u,v),d=dis[u]+dis[v]-2*dis[w],ret=d;
    	while(u!=w)a.push_back(u),u=fa[u];int p=a.size();
    	while(v!=w)b.push_back(v),v=fa[v];
    	a.push_back(w);while(b.size())a.push_back(b.back()),b.pop_back();
    	int s=0;
    	for(int i=1;i<=p;++i)s+=dis[a[i-1]]-dis[a[i]],ret=min(ret,max(s,d-s));
    	for(int i=p+1,l=a.size();i<l;++i)s+=dis[a[i]]-dis[a[i-1]],ret=min(ret,max(s,d-s));
    	return ret;
    }
    void dfs(int u,int ff)
    {
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;if(v==ff)continue;
    		dfs(v,u);
    		Node a=Query(1,1,n,dfn[v],low[v]);
    		Node b=((dfn[v]>1)?Query(1,1,n,1,dfn[v]-1):(Node){u,u})+((low[v]<n)?Query(1,1,n,low[v]+1,n):(Node){1,1});
    		ans=min(ans,max(max(Dis(a.u,a.v),Dis(b.u,b.v)),Brute(a.u,a.v)+Brute(b.u,b.v)+e[i].w));
    	}
    }
    int main()
    {
    	n=read();
    	for(int i=2;i<=n;++i)
    	{
    		int u=read(),v=read(),w=read();
    		Add(u,v,w);Add(v,u,w);
    	}
    	dfs1(1,0);dfs2(1,1);Build(1,1,n);
    	dfs(1,0);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    PAT顶级 1024 Currency Exchange Centers (35分)(最小生成树)
    Codeforces 1282B2 K for the Price of One (Hard Version)
    1023 Have Fun with Numbers (20)
    1005 Spell It Right (20)
    1092 To Buy or Not to Buy (20)
    1118 Birds in Forest (25)
    1130 Infix Expression (25)
    1085 Perfect Sequence (25)
    1109 Group Photo (25)
    1073 Scientific Notation (20)
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10614248.html
Copyright © 2020-2023  润新知