poj2253Frogger(最短路变形)及poj1797Heavy Transportation(最大生成树)

题目大意,有两只青蛙,分别在两个石头上,青蛙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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值