题目大意,有两只青蛙,分别在两个石头上,青蛙A想要到青蛙B那儿去,他可以直接跳到B的石头上,也可以跳到其他石头上,再从其他石头跳到B那儿,求青蛙从A到B的所有路径中最小的Frog Distance,定义Frog Distance为从A到B的一条路径中所跳的最大距离,例如,如果从A到B某条路径跳的距离是9,1,6,5,则Frog Distance就是9,注意每输出一个答案还要再空一行。
其实这道题就是求最小生成树的最大权,也就是说用最小生成树是可以做的,但是这道题只需将最短路中源点到终点的距离dis[i]换成源点到终点路径上边的最大距离,dis[i]=max(dis[i],dis[p]+cos[p][i})换成dis[i}换成min(dis[i},max(dis[p},cos[p}[i})就可以了。
32ms。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <stack>
#include <vector>
#include <string.h>
#include <queue>
#include <math.h>
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
#define mpow(X) ((X)*(X))
typedef long long LL;
using namespace std;
const int MAXN=205;
const double INF=1e10;
struct _Point
{
int x,y;
}point[MAXN];
double d[MAXN],cost[MAXN][MAXN];
bool vs[MAXN];
inline double dis(int u,int v)
{return sqrt((double)(mpow(point[u].x-point[v].x)+mpow(point[u].y-point[v].y))); }
void Dijst(int n,int beg)
{
ms(vs);
for(int i=0;i<n;i++) d[i]=cost[0][i];
for(int i=0;i<n;i++)
{
double minc=INF;
int p=-1;
for(int j=0;j<n;j++)
if(!vs[j]&&d[j]<minc)
minc=d[p=j];
vs[p]=true;
if(p==1) break;//答案已经出来了
for(int j=0;j<n;j++)
if(!vs[j]){
double maxx=max(d[p],cost[p][j]);
if(maxx<d[j]) d[j]=maxx;
}
}
}
int main(int argc, char const *argv[])
{
int ti=0,n;
while(scanf("%d",&n)!=EOF&&n)
{
for(int i=0;i<n;i++)
scanf("%d %d",&point[i].x,&point[i].y);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(i==j) cost[i][j]=0.0;
else cost[i][j]=cost[j][i]=dis(i,j);
Dijst(n,0);
printf("Scenario #%d\nFrog Distance = %.3f\n\n",++ti,d[1] );
}
return 0;
}
用Prim算法的做法,速度要再快一点,0ms。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <stack>
#include <vector>
#include <string.h>
#include <queue>
#include <math.h>
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
#define mpow(X) ((X)*(X))
typedef long long LL;
using namespace std;
const int MAXN=205;
const double INF=1e10;
struct _Point
{
int x,y;
}point[MAXN];
double lowc[MAXN],cost[MAXN][MAXN];
bool vs[MAXN];
inline double dis(int u,int v)
{return sqrt((double)(mpow(point[u].x-point[v].x)+mpow(point[u].y-point[v].y))); }
double ans;
void Prim(int n,int beg)
{
ms(vs);
for(int i=0;i<n;i++) lowc[i]=cost[0][i];
for(int i=0;i<n;i++)
{
double minc=INF;
int p=-1;
for(int j=0;j<n;j++)
if(!vs[j]&&lowc[j]<minc)
minc=lowc[p=j];
vs[p]=true;
ans=max(minc,ans);
if(p==1) break;
for(int j=0;j<n;j++)
if(!vs[j]&&lowc[j]>cost[p][j])
lowc[j]=cost[p][j];
}
}
int main(int argc, char const *argv[])
{
int ti=0,n;
while(scanf("%d",&n)!=EOF&&n)
{
for(int i=0;i<n;i++)
scanf("%d %d",&point[i].x,&point[i].y);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(i==j) cost[i][j]=0.0;
else cost[i][j]=cost[j][i]=dis(i,j);
ans=0.0;
Prim(n,0);
printf("Scenario #%d\nFrog Distance = %.3f\n\n",++ti,ans );
}
return 0;
}
与这道题相反一道题poj1797
最大生成树的最小权,当然同样这道题可以用dijkstra算法,只需将最短路中源点到终点的距离dis[i]换成源点到终点路径上边最小距离,dis[i]=max(dis[i],dis[p]+cos[p][i})换成dis[i}换成max(dis[i},min(dis[p},cos[p}[i})就可以了。(dis从大到小贪心)
以下是用Prim算法做的。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <stack>
#include <vector>
#include <string.h>
#include <queue>
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;
const int MAXN=1010;
const int INF=0x3f3f3f3f;
int cost[MAXN][MAXN],ans,upc[MAXN];
bool vs[MAXN];
//最大生成树
void Prim(int n,int beg)
{
ms(vs);
for(int i=1;i<n;i++) upc[i]=cost[0][i];
vs[0]=true;
for(int i=1;i<n;i++)
{
int maxc=0,p=-1;
for(int j=1;j<n;j++)
if(!vs[j]&&maxc<upc[j])
maxc=upc[p=j];
vs[p]=true;
ans=min(maxc,ans);
if(p==n-1) break;
for(int j=1;j<n;j++)
if(!vs[j]&&upc[j]<cost[p][j])
upc[j]=cost[p][j];
}
}
int main(int argc, char const *argv[])
{
int ti=0,t;
cin>>t;
while(++ti<=t)
{
int n,m;
scanf("%d %d",&n,&m);
ms(cost);
while(m--)
{
int a,b,w;
scanf("%d %d %d",&a,&b,&w);
a--,b--;
cost[a][b]=cost[b][a]=max(cost[a][b],w);
}
ans=INF;
Prim(n,0);
printf("Scenario #%d:\n%d\n\n",ti,ans);
}
return 0;
}