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
1 2 0
2 3 1
3 1 2
Sample Output
1
[数据范围]
0 < M < = 1000
0 < = Z < = 1000
[数据范围]
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;
}