题目大意如下:给定一个无向图,该图由两个或两个以上的联通分量构成,每个联通分量的直径定义为图中相距最远的两个点的距离;图的直径定义为图中所有联通分量直径的最大值。那么,如果再绘制一条连接两个联通分量的边,怎样使得最后的图的直径最小?
算法如下:
1、 用Floyd算法求出各个联通分量中任意两顶点i和j之间的距离dist[i][j],则此时的图的直径r1为所有点对之间的最大距离
2、 对于每个顶点i,求出距离它最远的点的距离len[i]
3、 最后,枚举所有不联通的点i和j,两者之间连接一条线,并且此时的新的距离为len[i]+len[j]+dist[i][j],并且令r2为这些距离中最大距离
4、 那么最终的直径为max(r1,r2)
- /*
- ID: millky
- PROG: cowtour
- LANG: C++
- */
- #include <iostream>
- #include <fstream>
- #include <string>
- #include <cmath>
- #include <algorithm>
- #include <vector>
- #include<iomanip>
- using namespace std;
- ifstream fin("cowtour.in");
- ofstream fout("cowtour.out");
- #define sqare(x) (x)*(x)
- struct point{int x,y;};
- int N;
- const double maxD = 1000000000.0;
- point co[150];
- double dist[150][150],lft[150],best[150][150];
- int res=-1;
- double getDist(int i,int j)
- {
- return sqrt((double)sqare(co[i].x-co[j].x)+(double)sqare(co[i].y-co[j].y));
- }
- void init()
- {
- fin>>N;
- string temp;
- for (int i=0;i<N;++i)fin>>co[i].x>>co[i].y;
- for (int i=0;i<N;++i) lft[i]=0;
- for (int i=0;i<N;++i) for(int j=0;j<N;++j)
- {
- dist[i][j]=maxD;
- best[i][j]=getDist(i,j);
- }
- for (int i=0;i<N;++i)
- {
- fin>>temp;
- for (int j=0;j<i;++j)
- if(temp[j]!='0')
- dist[i][j]=dist[j][i]=best[i][j];
- }
- }
- void floyd()
- {
- for (int k=0;k<N;++k)
- for (int i=0;i<N;++i)
- for (int j=0;j<N;++j)
- if(i!=j)dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
- for (int i=0;i<N;++i)
- for (int j=0;j<N;++j)
- if (dist[i][j]<maxD) lft[i]=max(lft[i],dist[i][j]);
- }
- double getRes()
- {
- double res=maxD;
- for (int i=0;i<N;++i)
- for (int j=0;j<i;++j)
- if (i!=j && dist[i][j]==maxD)res = min(res,lft[i]+lft[j]+best[i][j]);
- return max(res,*max_element(lft,lft+N));
- }
- int main()
- {
- init();
- floyd();
- fout.setf(ios::fixed);
- fout<<setprecision(6)<<getRes()<<endl;
- return 0;
- }
本文介绍了一种通过连接两个不连通的分量来最小化图直径的算法。使用Floyd算法预处理各分量内节点间的最远距离,并通过枚举找出最优连接方式。
927

被折叠的 条评论
为什么被折叠?



