• 【BZOJ】2237: [NCPC2009]Flight Planning


    题意

    (n(1 le n le 2500))个点的树,求删掉一条边再加上一条边使得还是一棵树,且任意两点最大距离最小。

    分析

    考虑枚举删掉每一条边,我们只需要考虑如何加边容易求得新树的最大距离。
    当然是直径的一半咯。

    题解

    枚举每一条边,然后求两个连通块的直径,然后最大距离(=max(len1, len2, (len1+1)/2+(len2+1)/2+1))

    #include <bits/stdc++.h>
    using namespace std;
    const int N=2505;
    struct E {
    	int next, to;
    }e[N<<1];
    int ihead[N], d[N], cnt, clr, n;
    void add(int x, int y) {
    	e[++cnt]=(E){ihead[x], y}; ihead[x]=cnt;
    	e[++cnt]=(E){ihead[y], x}; ihead[y]=cnt;
    }
    void dfs(int x, int f) {
    	for(int i=ihead[x]; i; i=e[i].next) {
    		int y=e[i].to;
    		if(y==f || i==clr || i==clr-1) {
    			continue;
    		}
    		d[y]=d[x]+1;
    		dfs(y, x);
    	}
    }
    int getlen(int x) {
    	memset(d, 0, sizeof(int)*(n+1));
    	dfs(x, 0);
    	for(int i=1; i<=n; ++i) {
    		if(d[i]>d[x]) {
    			x=i;
    		}
    	}
    	memset(d, 0, sizeof(int)*(n+1));
    	dfs(x, 0);
    	for(int i=1; i<=n; ++i) {
    		if(d[i]>d[x]) {
    			x=i;
    		}
    	}
    	return d[x];
    }
    int x[N], y[N];
    int main() {
    	scanf("%d", &n);
    	for(int i=1; i<n; ++i) {
    		scanf("%d%d", &x[i], &y[i]);
    		add(x[i], y[i]);
    	}
    	int ans=n;
    	for(int i=1; i<n; ++i) {
    		clr=i*2;
    		int len1=getlen(x[i]), len2=getlen(y[i]), a=(len1+1)/2, c=(len2+1)/2;
    		ans=min(ans, max(a+c+1, max(len1, len2)));
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
  • 相关阅读:
    js+canvas画随机4位验证码
    linux 下 查看 nginx 日志中访问前10 的 ip
    mysql greatest函数
    php 如何获取 post 传递的raw 数据
    php 监控文件变化 并上传到服务器
    php 如何统计本周 本月
    Yii2.0 GridView 的强大功能
    git 导出新修改的文件
    ubuntu16.04 下安装phpMyAdmin
    如何在ubuntu16.04 上搭建 phpstorm + xdebug 调试
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4985727.html
Copyright © 2020-2023  润新知