洛谷P1099 树网的核

末鹿安然 提交于 2019-12-02 03:18:23

题目

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

简化后的题意:
给定一棵带边权无根树
在其直径上求出一段长度不超过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;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!