传送门:http://poj.org/problem?id=2253
题目大意:给定n个点的坐标,求第一个点到第二个点的最短路中的最长路径。
解题思路:
算法一:借助Kruskal算法构造一颗伪的(不完全的)最小生成树,直到find(1)==find(2)为止,说明起点与终点均包含在 树中且是连通的,并且最短路就包含在这棵树里,Kruskal算法把边集都排了序,先合并的边都比后进来的短,所以满足题目要求的最短路中的最长路径。
算法二:借助最短路算法在松弛操作时候更新最长路径的值并记录,大致与最短路框架相似,Dijsktra,Floyd的复杂度都能满足题目时间要求。
Code:(Kruskal)
/* W w w mm mm 222222222 7777777777777 */
/* W w w w m m m m 222 22 7777 */
/* w w w w m m m m 22 777 */
/* w w w w m m m m 22 77 */
/* w w w w m m m m 222 77 */
/* w w w w m m m m 222 77 */
/* w w w w m m m m 222 77 */
/* w w w w m m m m 222 77 */
/* w w w w m m m m 222 77 */
/* ww ww m mm m 222222222222222 77 */
//#pragma comment(linker, "/STACK:102400000,102400000")
//C++
//int size = 256 << 20; // 256MB
//char *p = (char*)malloc(size) + size;
//__asm__("movl %0, %%esp\n" :: "r"(p));
//G++
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<ctime>
#include<deque>
#include<cmath>
#include<vector>
#include<string>
#include<cctype>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
#define REP(i,s,t) for(int i=(s);i<=(t);i++)
#define REP2(i,t,s) for(int i=(t);i>=s;i--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned long ul;
int n;
const int MAXN=205;//最大点数
const int MAXM=40005;//最大边数
const double inf=9999999999.0;
struct node
{
double x,y;
}p[MAXN];
double dist[MAXN][MAXN];
int F[MAXN];//并查集使用
struct Edge
{
int u,v;
double w;
} edge[MAXM]; //存储边的信息,包括起点/终点/权值
bool used[MAXM];
int tol;//边数,加边前赋值为0
void addedge(int u,int v,double w)
{
edge[tol].u=u;
edge[tol].v=v;
edge[tol++].w=w;
}
bool cmp(Edge a,Edge b)
{
//排序函数,讲边按照权值从小到大排序
return a.w<b.w;
}
int find(int x)
{
if(F[x]==-1)return x;
else return F[x]=find(F[x]);
}
double Kruskal(int n)//传入点数,返回最小生成树的权值,如果不连通返回-1
{
memset(F,-1,sizeof(F));
memset(used,false,sizeof(used));
sort(edge,edge+tol,cmp);
int cnt=0;//计算加入的边数
double ans=0;
for(int i=0; i<tol; i++)
{
int u=edge[i].u;
int v=edge[i].v;
double w=edge[i].w;
if(find(1)==find(2))
{
break;
}
int t1=find(u);
int t2=find(v);
if(t1!=t2)
{
ans+=w;
F[t1]=t2;
used[i]=true;
cnt++;
}
if(cnt==n-1)break;
}
if(cnt<n-1)return -1;//不连通
else return ans;
}
double dis(int i,int j)
{
double a=p[i].x-p[j].x;
double b=p[i].y-p[j].y;
return sqrt(a*a+b*b);
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("test.in","r",stdin);
#endif
int ca=1;
while(~scanf("%d",&n))
{
if(!n)
{
break;
}
REP(i,1,n)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
tol=0;
REP(i,1,n)
{
REP(j,1,n)
{
if(i==j)
{
dist[i][j]=inf;
continue;
}
dist[i][j]=dis(i,j);
addedge(i,j,dist[i][j]);
}
}
Kruskal(n);
double ans=-1;
REP(i,0,tol)
{
if(used[i])
{
ans=max(ans,edge[i].w);
}
}
printf("Scenario #%d\nFrog Distance = %.3f\n\n",ca++,ans);
}
return 0;
}