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
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://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\n",ans); 33 return 0; 34 }