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://www.xuebuyuan.com/609582.html
code:
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define maxn 205
 7 #define inf 1061109567
 8 using namespace std;
 9 char ch;
10 bool ok;
11 void read(int &x){
12     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
13     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
14     if (ok) x=-x;
15 }
16 int n,m,a,b,c,g[maxn][maxn],dis[maxn][maxn],rank[maxn][maxn],ans=inf;
17 int main(){
18     read(n),read(m);
19     memset(g,63,sizeof(g));
20     for (int i=1;i<=m;i++) read(a),read(b),read(c),g[a][b]=g[b][a]=min(g[a][b],c);
21     memcpy(dis,g,sizeof(g));
22     for (int i=1;i<=n;i++) dis[i][i]=0;
23     for (int k=1;k<=n;k++) for (int i=1;i<=n;i++) if (i!=k)
24         for (int j=1;j<=n;j++) if (j!=k&&j!=i) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
25     for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) rank[i][j]=j;
26     for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) for (int k=j+1;k<=n;k++)
27         if (dis[i][rank[i][j]]<dis[i][rank[i][k]]) swap(rank[i][j],rank[i][k]);
28     for (int i=1;i<=n;i++) ans=min(ans,dis[i][rank[i][1]]+dis[i][rank[i][2]]);
29     for (int i=1;i<=n;i++) for (int j=i+1;j<=n;j++) if (g[i][j]!=inf)
30         for (int a=1,b=2;b<=n;b++) if (dis[j][rank[i][a]]<dis[j][rank[i][b]])
31             ans=min(ans,dis[j][rank[i][a]]+dis[i][rank[i][b]]+dis[i][j]),a=b;
32     printf("%d
",ans);
33     return 0;
34 }
原文地址:https://www.cnblogs.com/chenyushuo/p/5125414.html