zoukankan      html  css  js  c++  java
  • [SDOI2011] 消防 (树的直径,尺取法)

    题目链接


    Solution

    (NOIP2007) 树网的核 .

    (dist_u) 为以 (u) 为根节点的子树中与 (u) 的最大距离.
    (~~~~dis_u)(u) 到直径中没有包括区间的一端的距离.
    (~~~~s) 为直径.
    题意很明确,要求直径上的一段区间使得 (Max(dist_u(uepsilon s),dis_u)) 最小.
    考虑 (O(n)) ,直接在直径上尺取就好了...
    考虑 (O(nlogn)) ,直接二分+枚举起点就好了.
    然而数据过水,直接打的 (O(n^2)) ,结果(A)了.


    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1008;
    struct sj{
    int to,next,w;
    }a[maxn*2];
    int head[maxn],size;
    int n,s,x,y,w;
    int read()
    {
    	int f=1,w=0; char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch<='9'&&ch>='0'){w=w*10+ch-'0';ch=getchar();}
    	return f*w;
    }
    void add(int x,int y,int w)
    {
    	a[++size].to=y;
    	a[size].next=head[x];
    	head[x]=size;a[size].w=w;
    }
    
    int last,num,now,cnt,v[maxn],bcnt;
    int ans[maxn],maxx,road[maxn];
    int dist[maxn],b[maxn],ansb[maxn];
    int sum[maxn];
    void dfs(int x)
    {
    	v[x]=1;
    	road[++cnt]=x;
    	for(int i=head[x];i;i=a[i].next)
    	{
    		 int tt=a[i].to;
    		 if(!v[tt])
    		 {
    		 	now+=a[i].w;
    		 	b[++bcnt]=a[i].w;
    		 	dfs(tt); cnt--;bcnt--;
    		 	now-=a[i].w;
    		 }
    	}
    	if(now>maxx)
    	{
    		num=cnt; last=x; maxx=now;
    		for(int i=1;i<=cnt;i++)
    		ans[i]=road[i],ansb[i]=b[i];
    	}
    }
    
    void getdist(int x)
    {
    	v[x]=1;
    	maxx=max(maxx,now);
    	for(int i=head[x];i;i=a[i].next)
    	{
    		int tt=a[i].to;
    		if(!v[tt])
    		{
    			now+=a[i].w;
    			getdist(tt);
    			now-=a[i].w;
    		}
    	}
    }
    
    int main()
    {
    	n=read(); s=read();
    	for(int i=1;i<n;i++)
    	{
    		x=read(); y=read(); w=read();
    		add(x,y,w); add(y,x,w);
    	}
    	dfs(1);
    	memset(v,0,sizeof(v));
    	maxx=0; cnt=0; now=0;
    	dfs(last);
    	memset(v,0,sizeof(v));
    	for(int i=1;i<=num;i++)v[ans[i]]=1;
    	for(int i=2;i<=num;i++)sum[i]=sum[i-1]+ansb[i-1];
    	for(int i=1;i<=num;i++)
    	{maxx=0,getdist(ans[i]),dist[i]=maxx;}
    	
    	int q[maxn]={0},kk=192608173;
        int h=1,t=0;
        for(int i=1;i<=num;i++)
        {
    	    int fuck=-1;
        	for(int j=i;j<=num;j++)
        	{
        		fuck=max(fuck,dist[j]);
    			if(sum[j]-sum[i]>s)break;
            	kk=min(kk,max(max(sum[i],sum[num]-sum[j]),fuck));
        	}
        }
        cout<<kk<<endl;
    }
    
  • 相关阅读:
    Codeforces Round #622 (Div. 2)
    Knapsack Cryptosystem 牛客团队赛
    HDU 2586(LCA欧拉序和st表)
    P3865 【模板】ST表
    P2023 [AHOI2009]维护序列 区间加乘模板
    P1558 色板游戏 线段树(区间修改,区间查询)
    Codeforces Round #621 (Div. 1 + Div. 2) D
    Codeforces Round #620 (Div. 2) E
    Educational Codeforces Round 82 (Rated for Div. 2)
    洛谷P1638 逛画展
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/9506545.html
Copyright © 2011-2022 走看看