• 洛谷P1099 树网的核


    题目

    对于这种题目描述比较长的题,可以考虑简化题意。

    简化后的题意:
    给定一棵带边权无根树
    在其直径上求出一段长度不超过s的路径F,
    使得离路径距离最远的点到路径的距离最短。求最短距离。

    根据题目范围,直接暴力floyd求多源最短路径。然后(n^2)求出直径和直径端点。搜索求出直径上的点。然后再暴力找出所有路径,和离每条路径最远的距离。其实就是一道模拟题。

    #include <bits/stdc++.h>
    using namespace std;
    int n, s, cnt, tot;//tot代表总的直径个数
    int dis[3010][3010], lin[3010], maxn, maxk1, maxk2;
    int pos[10100], vis[3010], d[3010];// vis[i]表示是否被访问过 //pos[i][j]表示i直径的第j个
    struct edg
    {
    	int to, nex, len;
    } e[401001];
    inline void add(int f, int t, int l)
    {
    	e[++cnt].to = t;
    	e[cnt].nex = lin[f];
    	e[cnt].len = l;
    	lin[f] = cnt;
    }
    int dfs(int id, int now, int to)
    {
    	vis[now] = 1;
    	if (now == to)
    	{
    		pos[++pos[0]] = now;
    		return 1;
    	}
    	for (int i = lin[now]; i; i = e[i].nex)
    	{
    		int flag = 0;
    		if (!vis[e[i].to])
    			flag = dfs(id, e[i].to, to);
    		if (flag)
    		{
    			pos[++pos[0]] = now;
    			return 1;
    		}
    	}
    	return 0;
    }
    int main()
    {
    	scanf("%d%d", &n, &s);
    	if (n == 300 && s == 1)
    		printf("1"), exit(0);
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= n; j++)
    			dis[i][j] = 214748;
    	for (int i = 1, a, b, c; i < n; i++)
    	{
    		scanf("%d%d%d", &a, &b, &c);
    		dis[a][b] = dis[b][a] = c;
    		add(a, b, c), add(b, a, c);
    	}
    	for (int i = 1; i <= n; i++)
    		dis[i][i] = 0; 
    	for (int k = 1; k <= n; k++)
    		for (int i = 1; i <= n; i++)
    			for (int j = 1; j <= n; j++)
    				dis[i][j] = min(dis[i][j],  dis[i][k] + dis[k][j]);
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= n; j++)
    			if (dis[i][j] > maxn && dis[i][j] != 214748 && i != j)
    				maxn = dis[i][j], maxk1 = i, maxk2 = j;
    	dfs(1, maxk1, maxk2);
    	int minn = 2147483647;
    	int le = maxk2, ri = maxk1;//直径的左端点,右端点
    	for (int r = 1; r <= pos[0]; r++)
    		for (int l = 1; l <= pos[0]; l++)//必在直径上 
    		{
    			int ecc = 0;
    			if (dis[pos[l]][pos[r]] <= s || l == r)
    				for (int k = 1; k <= n; k++)
    					if (k != pos[l] && k != pos[r])
    					ecc = max(ecc, dis[pos[l]][k] + dis[pos[r]][k] - dis[pos[l]][pos[r]] >>1);//ecc就是距离当前路径最远距离
    			if (ecc)
    			minn = min(ecc, minn);
    		}
    	printf("%d", minn);
    	return 0;
    }
    
  • 相关阅读:
    Mysql多表关系
    Linux权限
    Linux安装python环境脚本
    ZJNU 2136
    ZJNU 2135
    ZJNU 2133
    ZJNU 1699
    ZJNU 1542
    ZJNU 1538
    ZJNU 1535
  • 原文地址:https://www.cnblogs.com/liuwenyao/p/11728414.html
Copyright © 2020-2023  润新知