POJ 2253 Frogger (最小生成树 or 最短路变形)

来源:互联网 发布:excel如何保护数据 编辑:程序博客网 时间:2024/06/13 04:13

传送门: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;//边数,加边前赋值为0void 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;}
0 0