2182: [Spoj1479]The GbAaY Kingdom最小直径生成树

等价于求图的绝对中心
这个东西是好几条折线组成的一个东西,我们用单调栈去维护它.显然设现在枚举的边为(u,v ,w) 该点为p 则有 dis[p][i] = min(dis[u][i] + k , dis[v][i] + w - k); k = dis[u][p];
选取一个k使得对于所有dis[p][i]的最大值最小.显然如果说dis[u][i] > dis[u][j] 并且 dis[v][i]>dis[v][j] 则显然j一定对答案无贡献可舍去,剩下就是维护一个单调栈,按到u的距离排序,另一维上升时计算交点与答案取min.

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 2e2 + 5;
const int M = 1e5 + 5;

int dis[N][N] , way[N][N] , n , m , x , y , w , rk[N][N];

#define PER(i , a , b) for(int i = a;i <= b;++ i)
#define Min(x , y) x = min(x , y)

bool cmp(int x , int y) {
    return dis[w][x] < dis[w][y];
}

int main(void) {
    scanf("%d%d" , &n , &m);
    PER(i , 1 , n) PER(j , 1 , n) dis[i][j] = way[i][j] = 1e6;
    for(int i = 1;i <= m;++ i) {
        scanf("%d%d%d" , &x , &y , &w);
        way[x][y] = way[y][x] = min(way[x][y] , w);
    }
    for(int i = 1;i <= n;++ i) {
        way[i][i] = 0;
        for(int j = 1;j <= n;++ j) dis[i][j] = way[i][j];
    }
    PER(k , 1 , n) PER(i , 1 , n) PER(j , 1 , n) Min(dis[i][j] , dis[i][k] + dis[k][j]);
    PER(i , 1 , n) {
        w = i;
        PER(j , 1 , n) rk[i][j] = j;
        sort(rk[i] + 1 , rk[i] + n + 1 , cmp);
    }
    int ans = 2e9;
    PER(i , 1 , n) {
        PER(j , 1 , n) if(i != j){
            for(int cmp = n , k = n - 1;k >= 1;-- k) if(dis[j][rk[i][k]] > dis[j][rk[i][cmp]]) Min(ans , dis[i][rk[i][k]] + dis[j][rk[i][cmp]] + way[i][j]), cmp = k;
        }
    }
    printf("%d\n" , ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值