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

来源:互联网 发布:mac book 能做什么 编辑:程序博客网 时间:2024/06/07 05:07

等价于求图的绝对中心
这个东西是好几条折线组成的一个东西,我们用单调栈去维护它.显然设现在枚举的边为(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