zoukankan      html  css  js  c++  java
  • [SDOI2013]直径 题解

    题面

    这道题明显的一定要找到直径的具体路径,所以两遍dfs是比较好的选择;

    第一问是一道弱智题吧?

    主要难度全部分摊在了第二问;

    其实不难,先找到任意一个直径;

    对于任意一个在直径上的点:

    设nxt[i]表示这个点的下一个位置,pre[i]表示这个点的上一个位置;

    ls[i]表示这个点到直径的左端点的距离,rs[i]则表示这个点到直径的右端点的距离;

    我们再dfs一遍,找到每个点在不经过直径上任意点的时候所能到达的最远处,这个值记为dismax[i];

    那么我们从直径的左端点开始向右推进,直到找到一个点的rs[i]=dismax[i](这意味着存在一条直径使得下一条边不是必经边);

    我们注意到,从右向左也需要这么做一次。毕竟我们无法保证从左端点开始就是必经边;

    然后就可以A掉了;

    #include <bits/stdc++.h>
    #define int long long
    #define inc(i,a,b) for(register int i=a;i<=b;i++)
    using namespace std;
    const int MXR=2e5+10;
    int head[MXR],cnt;
    class littlestar{
    	public:
    	int to,nxt,w;
    	void add(int u,int v,int gg){
    		to=v; nxt=head[u]; 
    		w=gg;head[u]=cnt;
    	}
    }star[MXR<<1];
    int n,m;
    template<class nT>
    void read(nT& x)
    {
    	char c;while(c=getchar(),!isdigit(c));
    	x=c^48;while(c=getchar(),isdigit(c)) x=x*10+c-48;
    }
    int dis[MXR],root1,root2,f[MXR],g[MXR];
    void dfs(int u,int fa)
    {
    	f[u]=fa;
    	for(int i=head[u];i;i=star[i].nxt){
    		int v=star[i].to;
    		if(v==fa) continue;
    		dis[v]=dis[u]+star[i].w;
    		dfs(v,u);
    		g[v]=star[i].w;
    	}
    }
    int judge[MXR],ls[MXR],rs[MXR],nxt[MXR],pre[MXR];
    int dismax[MXR];
    void dfs2(int u,int fa)
    {
    	for(int i=head[u];i;i=star[i].nxt){
    		int v=star[i].to;
    		if(v==fa) continue;
    		dfs2(v,u);
    		if(judge[v]==0){
    			dismax[u]=max(dismax[u],star[i].w+dismax[v]);
    		}
    	}
    }
    signed main()
    {
    	read(n);
    	inc(i,1,n-1){
    		int a,b,c;
    		read(a);read(b);read(c);
    		star[++cnt].add(a,b,c);
    		star[++cnt].add(b,a,c);
    	}
    	root1=1;
    	dfs(root1,0);
    	int maxn=-INT_MAX;
    	inc(i,1,n) if(dis[i]>maxn) maxn=dis[i],root2=i;
    	memset(dis,0,sizeof(dis)); maxn=-INT_MAX; memset(f,0,sizeof(f));
    	dfs(root2,0);
    	inc(i,1,n) if(dis[i]>maxn) maxn=dis[i],root1=i;
    	int tmpx=root1;
    	while(tmpx!=root2){
    		nxt[tmpx]=f[tmpx];
    		pre[f[tmpx]]=tmpx;		
    		ls[f[tmpx]]=ls[tmpx]+g[tmpx];
    		rs[tmpx]=maxn-ls[tmpx];
    		judge[tmpx]=1;
    		tmpx=f[tmpx];
    	}
    	judge[root2]=1;
    	dfs2(root2,0);
    	int goal=0;
    	tmpx=root1;
    	while(tmpx!=0){
    		if(rs[tmpx]==dismax[tmpx]){
    			break;
    		}
    		tmpx=nxt[tmpx];
    	}
    	if(tmpx==0) tmpx=pre[tmpx];
    	goal=tmpx;
    	while(tmpx!=0){
    		if(ls[tmpx]==dismax[tmpx]){
    			break;
    		}
    		tmpx=pre[tmpx];
    	}
    	if(tmpx==0) tmpx=nxt[tmpx];
    	int ans=0;
    	while(tmpx!=goal){
    		++ans;
    		tmpx=nxt[tmpx];
    	}
    	cout<<maxn<<endl;
    	cout<<ans;
    	
    }
    /*
    6
    3  1 1000
    1  4 10
    4  2 100
    4  5 50
    4  6 100
    */
    
  • 相关阅读:
    ffmpeg一些filter使用方法、以及一些功能命令
    Hibernate调试——定位查询源头
    emmet语法
    [心得]传统IT转互联网面试经验分享
    Java中的集合类型的继承关系图
    Java的IO操作中有面向字节(Byte)和面向字符(Character)两种方式
    oracle求时间差的常用函数
    jdbc读取新插入Oracle数据库Sequence值的5种方法
    Xpath语法格式整理
    Oracle中 Instr 这个函数
  • 原文地址:https://www.cnblogs.com/kamimxr/p/11799096.html
Copyright © 2011-2022 走看看