666 专题六 最短路练习

Problem A.Til the Cows Come Home

d.点N到点1的最短路径

s.

c.Dijkstra算法+堆优化

/*
Dijkstra算法+堆优化
使用优先队列优化,复杂度O(E log E)
使用优先队列优化Dijkstra算法
复杂度O(E log E)
注意对vector<Edge>E[MAXN]进行初始化后加边
*/
#include<iostream>
#include<stdio.h>
#include<vector>
#include<string.h>
#include<queue>
using namespace std;

const int INF=0x3f3f3f3f;
const int MAXN=1024;
struct qnode{
    int v;
    int c;
    qnode(int _v=0,int _c=0):v(_v),c(_c){}
    bool operator <(const qnode &r)const{
        return c>r.c;
    }
};
struct Edge{
    int v,cost;
    Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}
};
vector<Edge>E[MAXN];
bool vis[MAXN];
int dist[MAXN];
//点的编号从1开始
void Dijkstra(int n,int start){
    memset(vis,false,sizeof(vis));
    for(int i=1;i<=n;i++)dist[i]=INF;
    priority_queue<qnode>que;
    while(!que.empty())que.pop();
    dist[start]=0;
    que.push(qnode(start,0));
    qnode tmp;
    while(!que.empty()){
        tmp=que.top();
        que.pop();
        int u=tmp.v;
        if(vis[u])continue;
        vis[u]=true;
        for(int i=0;i<E[u].size();i++){
            int v=E[tmp.v][i].v;
            int cost=E[u][i].cost;
            if(!vis[v]&&dist[v]>dist[u]+cost){
                dist[v]=dist[u]+cost;
                que.push(qnode(v,dist[v]));
            }
        }
    }
}
void addedge(int u,int v,int w){
    E[u].push_back(Edge(v,w));
}

int main(){

    int T,N;
    int u,v,w;

    while(~scanf("%d%d",&T,&N)){
        for(int i=1;i<=N;++i){
            E[i].clear();
        }

        for(int i=0;i<T;++i){
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
        }

        Dijkstra(N,N);
        printf("%d\n",dist[1]);
    }

    return 0;
}
View Code

 

Problem B.Frogger(不错)

d.湖中有很多石头,两只青蛙分别位于两块石头上。其中一只青蛙要经过一系列的跳跃,先跳到其他石头上,最后跳到另一只青蛙那里。目的是求出所有路径中最大变长的最小值(就是在到达目的地的路径中,找出青蛙需要跳跃的最大边长的最小的值)。

s.Dijkstra单源最短路的变形,不是求最短路径了,而是求路径中最大的一条边最小,修改一下代码比较部分就行了。

c.Dijkstra单源最短路

/*
Dijkstra单源最短路
权值必须是非负
单源最短路径,Dijkstra算法,邻接矩阵形式,复杂度为O(n^2)
求出源beg到所有点的最短路径,传入图的顶点数,和邻接矩阵cost[][]
返回各点的最短路径lowcost[],路径pre[].pre[i]记录beg到i路径上的父结点,pre[beg]=-1
可更改路径权类型,但是权值必须为非负
*/
#include<iostream>
#include<stdio.h>
#include<math.h>
using namespace std;

const int MAXN=205;
#define typec double
const typec INF=5000000;//防止后面溢出,这个不能太大
bool vis[MAXN];
int pre[MAXN];
void Dijkstra(typec cost[][MAXN],typec lowcost[],int n,int beg){
    for(int i=0;i<n;i++){
        lowcost[i]=INF;vis[i]=false;pre[i]=-1;
    }
    lowcost[beg]=0;
    for(int j=0;j<n;j++){
        int k=-1;
        double Min=INF;
        for(int i=0;i<n;i++)
            if(!vis[i]&&lowcost[i]<Min){
                Min=lowcost[i];
                k=i;
            }
        if(k==-1)break;
        vis[k]=true;
        for(int i=0;i<n;i++)
            if(!vis[i]&&lowcost[k]<lowcost[i]&&cost[k][i]<lowcost[i]){
                lowcost[i]=lowcost[k]>cost[k][i]?lowcost[k]:cost[k][i];
                pre[i]=k;
            }
    }
}

int main(){

    int n;
    double x[MAXN],y[MAXN];
    double cost[MAXN][MAXN];
    double lowcost[MAXN];
    int C=0;

    while(~scanf("%d",&n)){

        if(n==0)break;

        for(int i=0;i<n;++i){
            scanf("%lf%lf",&x[i],&y[i]);
        }

        for(int i=0;i<n;++i){
            for(int j=0;j<n;++j){
                cost[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
            }
        }

        Dijkstra(cost,lowcost,n,0);

        printf("Scenario #%d\n",++C);
        printf("Frog Distance = %.3f\n",lowcost[1]);
        printf("\n");
    }

    return 0;
}
View Code

 

Problem C.Heavy Transportation

d.和上个题相反,求路径中最小的一条边最大

s.和上个题类似。不过用下面这个堆优化的模板时,注意要修改下优先队列的优先级,这个题是最大值优先。

c.Dijkstra算法+堆优化

/*
Dijkstra算法+堆优化
使用优先队列优化,复杂度O(E log E)
使用优先队列优化Dijkstra算法
复杂度O(E log E)
注意对vector<Edge>E[MAXN]进行初始化后加边
*/
#include<iostream>
#include<stdio.h>
#include<vector>
#include<string.h>
#include<queue>
using namespace std;

const int INF=0x3f3f3f3f;
const int MAXN=1024;
struct qnode{
    int v;
    int c;
    qnode(int _v=0,int _c=0):v(_v),c(_c){}
    bool operator <(const qnode &r)const{
        return c<r.c;
    }
};
struct Edge{
    int v,cost;
    Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}
};
vector<Edge>E[MAXN];
bool vis[MAXN];
int dist[MAXN];
//点的编号从1开始
void Dijkstra(int n,int start){
    memset(vis,false,sizeof(vis));
    //for(int i=1;i<=n;i++)dist[i]=INF;
    memset(dist,0,sizeof(dist));//这里不是初始化为INF了
    priority_queue<qnode>que;
    while(!que.empty())que.pop();
    dist[start]=INF;//出发点设为最大
    que.push(qnode(start,INF));
    qnode tmp;
    while(!que.empty()){
        tmp=que.top();
        que.pop();
        int u=tmp.v;
        if(vis[u])continue;
        vis[u]=true;
        for(int i=0;i<E[u].size();i++){
            int v=E[tmp.v][i].v;
            int cost=E[u][i].cost;
            if(!vis[v]&&dist[v]<dist[u]&&dist[v]<cost){
                dist[v]=dist[u]<cost?dist[u]:cost;
                que.push(qnode(v,dist[v]));
            }
        }
    }
}
void addedge(int u,int v,int w){
    E[u].push_back(Edge(v,w));
}

int main(){

    int T;
    int n,m;
    int u,v,w;
    int C=0;

    scanf("%d",&T);

    while(T--){

        scanf("%d%d",&n,&m);

        for(int i=1;i<=n;++i){
            E[i].clear();
        }

        for(int i=0;i<m;++i){
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
        }

        Dijkstra(n,1);

        printf("Scenario #%d:\n",++C);
        printf("%d\n",dist[n]);
        printf("\n");
    }

    return 0;
}
View Code

 

posted @ 2016-01-18 15:53  gongpixin  阅读(261)  评论(0编辑  收藏  举报