【bzoj2180】【最小直径生成树】【图的绝对中心】

Description

输入一个无向图G=(V,E),W(a,b)表示边(a,b)之间的长度,求一棵生成树T,使得T的直径最小。树的直径即树的最长链,即树上距离最远的两点之间路径长度。

Input

输入第一行包括两个整数N,M,分别表示点与边的个数。 以下M行,每行3个整数X,Y,Z,描述一条无向边(X,Y),且W(X,Y)=Z。

Output

仅一个数,即最小直径。

Sample Input

3 3
1 2 0
2 3 1
3 1 2

Sample Output

1
[数据范围]
0 < M < = 1000
0 < = Z < = 1000
题解:http://blog.csdn.net/crazy_ac/article/details/8816877自己去学吧。。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 210
#define INF 707406378
using namespace std;
int f[N][N],d[N][N],ans,m,n,x,y,z,p[N][N];
void floyed(){
    for (int k=1;k<=n;k++)
      for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
          if (i!=j&&j!=k&&k!=i){f[i][j]=min(f[i][j],f[i][k]+f[k][j]);}
}
void getrank(){
  for (int i=1;i<=n;i++){
    for (int j=1;j<=n;j++) p[i][j]=j;
    for (int j=1;j<n;j++)
     for (int k=j+1;k<=n;k++)
       if (f[i][p[i][j]]>f[i][p[i][k]]) swap(p[i][j],p[i][k]); 
  } 
}
void getans(){
  ans=INF;
  for (int u=1;u<=n;u++)
   for (int v=1;v<=n;v++)
    if (d[u][v]!=INF){
     ans=min(ans,min(f[u][p[u][n]]<<1,f[v][p[v][n]]<<1));int t=n; 
     for (int i=n-1;i>=1;i--)
      if (f[v][p[u][t]]<f[v][p[u][i]]){ans=min(ans,f[u][p[u][i]]+f[v][p[u][t]]+d[u][v]);t=i;}
    }
}
int main(){
   scanf("%d%d",&n,&m);memset(f,127/3,sizeof(f));memset(d,127/3,sizeof(d));
   for (int i=1;i<=n;i++) f[i][i]=d[i][i]=0;
   for (int i=1;i<=m;i++){scanf("%d%d%d",&x,&y,&z);f[x][y]=f[y][x]=d[x][y]=d[y][x]=z;}
   floyed();getrank();getans();
   cout<<ans<<endl; 
} 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值