zoukankan      html  css  js  c++  java
  • poj 1135 最短路(优先队列堆优化Dijkstra实现)

    Problem: http://poj.org/problem?id=1135

    求图中距离1点最远(包括点和边上的点)的距离

    先对所有点求单源(点1)最短路

    然后每条边上的点距离1点最远的距离必为边两端点到点1的最短距离和该边的长度 三者和的一半

    现在点到源(点1)的距离知道了 边到源(点1)的距离也知道了 只需要比较两者了

    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    #define MAXN 510
    #define MAXE 250010
    int n,m,size,head[MAXN],A[MAXE],B[MAXE],pre[MAXN];
    double C[MAXE],dist[MAXN];
    bool vis[MAXN];
    struct Edge{
        int to,next;
        double w;
    }e[MAXE<<1];
    void add_edge(int u,int v,double w){//链式前向星存图 
        e[size].to=v;
        e[size].w=w;
        e[size].next=head[u];
        head[u]=size++;
    }
    void Seap(int &a,int &b){
        int c=a;
        a=b;
        b=c;
    }
    void work(int s){
        for(int i=1;i<=n;i++)dist[i]=-1;
        memset(vis,false,sizeof(vis));
        dist[s]=0;
        priority_queue<pair<double,int> > heap;//优先队列实现堆 
        heap.push(make_pair(0,s));
        while(!heap.empty()){//堆优化Dijkstra 
            int u=heap.top().second;
            heap.pop();
            if(vis[u])continue;
            vis[u]=true;
            int k=head[u];
            while(k>=0){
                if(dist[e[k].to]<0 || dist[e[k].to]>dist[u]+e[k].w){
                    pre[e[k].to]=u;
                    dist[e[k].to]=dist[u]+e[k].w;
                    heap.push(make_pair(-dist[e[k].to],e[k].to));
                }
                k=e[k].next;
            }
        }
        int k1,k2;
        double ans1=0,ans2=0;
        for(int i=1;i<=n;i++){//求距源最远的点 
            if(dist[i]>ans1){
                ans1=dist[i];
                k1=i;
            }
        }
        for(int i=0;i<m;i++){//求距源最远的边 
            double l=dist[A[i]]+dist[B[i]]+C[i];
            if(l/2>ans2){
                ans2=l/2;
                k2=i;
            }
        }
        printf("The last domino falls after ");
    
        if(ans1>=ans2)printf("%.1f seconds, at key domino %d.
    ",ans1,k1);
        else{
            if(A[k2]>B[k2])Seap(A[k2],B[k2]);
            printf("%.1f seconds, between key dominoes %d and %d.
    ",ans2,A[k2],B[k2]);
        }
    }
    void init(){
        size=0;
        memset(head,-1,sizeof(head));
        for(int i=0;i<m;i++){
            scanf("%d%d%lf",&A[i],&B[i],&C[i]);
            add_edge(A[i],B[i],C[i]);
            add_edge(B[i],A[i],C[i]);
        }
    }
    int main(){
        int t=0;
        while(scanf("%d%d",&n,&m),n+m){
            init();
            printf("System #%d
    ",++t);
            work(1);
            printf("
    ");
        }
        return 0;
    }
    View Code

    题中边长l没给范围是个坑,直接用double是明智滴真知>>>>>.<<<<<<

  • 相关阅读:
    03:信号与槽,以字体修改为例
    赞不绝口点赞器原作者的撤项信
    钉钉魔铃 铃声切换器 1.0 项目失败
    KC开发组官方网站
    搜索引擎知识
    现在的手机厂家真浮躁
    02:QT的第一个程序
    第一次做编程语言的英语阅读理解
    mysql 报错[Err] [Dtf] 1292
    Mysql 精确查询是否字段中包含某个字符串
  • 原文地址:https://www.cnblogs.com/cshhr/p/3545070.html
Copyright © 2011-2022 走看看