zoukankan      html  css  js  c++  java
  • [Dijkstra] POJ 2253 Frogger | POJ 1797 Heavy Transportation | POJ 3268 Silver Cow Party

    POJ 2253 Frogger | POJ 1797 Heavy Transportation | POJ 3268 Silver Cow Party

    Dijkstra使用链式前向星实现的G=(V,E)

    https://malash.me/200910/linked-forward-star/#comment-25291

    由于MAXN上限太大开不了邻接矩阵,又由于卡时间用vector会TLE。

    typedef long long LL;
    typedef pair<LL,int> Pair;
    const int MAX_P = 1000003;
    const int INF = 0x3fffffff;
    int P;// number of stops including CCS
    int Q;// the number of bus lines
    
    /* MLE: 1e12
     * int G[MAX_P][MAX_P];// 1-indexed
     */
    /* TLE: >8000ms
     * vector<vector<Pair>> 
     * vector<Pair> GS[MAX_P];
     * vector<Pair> GD[MAX_P];
     * AC: 2188ms
     */
    int dis[MAX_P];
    int vis[MAX_P];
    /*-----数据结构------*/
    int head[MAX_P];	//记录以索引i为源点的边的链表的首条边在edge数组中的地址
    int rhead[MAX_P];
    struct Edge{
        int dst;
        int w;
        int next;
    }edge[MAX_P*2];		// 双向Dijkstra中head和rhead共用cnt,若edge开为MAX_P会越界
    /*-------add--------*/
    int cnt=1;
    void add(int head[],int S,int D,int w){
        edge[cnt].dst = D;
        edge[cnt].w = w;
        edge[cnt].next = head[S];
        head[S] = cnt++;
        /* 不能用++cnt, 只能用cnt++
         * 因为数组edge索引和head维护的当前链表头对应的边在edge数组 
         * 且head==0标志到达链表尾
         */
    }
    /*------------------*/
    
    void dijkstra(int head[]){
        dis[1] = 0;
        priority_queue<Pair,vector<Pair>,greater<Pair>> Q;// min-heap
        Q.push(Pair(dis[1],1));
        while(!Q.empty()){
            Pair p = Q.top();
            Q.pop();
            int cur = p.second;
            if(vis[cur]) continue;
            vis[cur] = 1;
            for(int i=head[cur];i!=0;i=edge[i].next){
                int nxt = edge[i].dst;
                if(vis[nxt]) continue;
                int prc =edge[i].w;
                if(dis[cur] + prc < dis[nxt]){
                    dis[nxt] = dis[cur] + prc;
                    Q.push(Pair(dis[nxt],nxt));
                }
            }
        }
    }
    
    int main(){
        int N;
        scanf("%d",&N);
        for(int n=0;n<N;n++){
            fill(head,head+MAX_P,0);
            fill(rhead,rhead+MAX_P,0);
            cnt = 1;
            scanf("%d %d",&P,&Q);
            int S,D,price;
            for(int q=0;q<Q;q++){    
                scanf("%d %d %d",&S,&D,&price);
                add(head,S,D,price);
                add(rhead,D,S,price);
            }
            LL ans=0;
            fill(dis,dis+MAX_P,INF);
            fill(vis,vis+MAX_P,0);
            dijkstra(head);
            for(int i=1;i<=P;i++){
                ans += dis[i];
            }
            fill(dis,dis+MAX_P,INF);
            fill(vis,vis+MAX_P,0);
            dijkstra(rhead);
            for(int i=1;i<=P;i++){
                ans += dis[i];
            }
            
            // lld not ld
            printf("%lld
    ", ans);
        }
        return 0;
    }
    

    Dijkstra更新条件不同于最短路

    POJ 2253 minmax distance;

    POJ 1797 maxmin distance,距离初始化与minmax恰好相反。

    下面只给出 POJ 2253 minmax题目AC解:

    #include"stdio.h"
    #include"string.h"
    #include"math.h"
    #include<vector>
    #include<queue>
    #include<functional>
    #include<algorithm>
    using namespace std;
    typedef pair<int,int> Pair;
    const int MAX_N = 203;
    int N;
    double G[MAX_N][MAX_N];
    vector<Pair> pos;
    int vis[MAX_N];
    double frogd[MAX_N];
    double EuDist(Pair p1,Pair p2){
        double x=p1.first-p2.first;
        double y=p1.second-p2.second;
        return sqrt(x*x+y*y);
    }
    void dijkstra(int s){
        frogd[s]=0;
        priority_queue<Pair,vector<Pair>,greater<Pair>> Q;
        Q.push(Pair(frogd[s],s));
        while(!Q.empty()){
            Pair p = Q.top();
            Q.pop();
            int cur = p.second;
            /* --------
            /* bfs标记vis的位置与push同时操作;
            /* dijkstra标记vis的操作在pop之后:
            /*   刚push进去的距离可能大于先前就在queue中的,
            /*   因此下一个加入vis集合的不一定是刚push进去的
               --------*/
            if(vis[cur]) continue;
            vis[cur]=1;
            double tmp_min=G[0][1];
            // int tmp_next;
            for(int j=0;j<N;j++){
                if(j==cur) continue;
                if(G[cur][j]==-1) continue;
                if(vis[j]) continue;
                if(max(frogd[cur],G[cur][j]) < frogd[j]) {
                    frogd[j] = max(G[cur][j],frogd[cur]);
                    Q.push(Pair(frogd[j],j));
                }
            }
        }
    }
    int main(){
        int t=0;
        while(scanf("%d",&N)!=EOF){
            t++;
            if(N==0) break;
            pos.clear();
            // do not use memset!
            fill(G[0],G[0]+MAX_N*MAX_N,-1);
            fill(vis,vis+MAX_N,0);
            fill(frogd,frogd+MAX_N,999999999);
            for(int n=0;n<N;n++){
                int x,y;
                scanf("%d %d",&x,&y);
                pos.push_back(Pair(x,y));//0-Freaddy, 1-Fiona
            }
            for(int i=0;i<N-1;i++){
                for(int j=i+1;j<N;j++){
                    G[i][j]=G[j][i] = EuDist(pos[i],pos[j]);
                }
            }
            dijkstra(0);
            printf("Scenario #%d
    ", t);
            printf("Frog Distance = %.3f
    ", frogd[1]);
            printf("
    ");
        }
        return 0;
    }
    

    反向Dijkstra

    POJ 3268 Silver Cow Party

    求任一点和X的往返距离:每个点作为源进行一次dijkstra会TLE;事实上只用两遍Dijkstra(正向和反向)。

    下面给反向DijsktraAC代码,其中数据初始化和正向相同,只有判断和更新条件略不同。

    fill(disDst,disDst+MAX_N,0x3fffffff);
    
    void dijkstraDst(int dst){
        disDst[dst]=0;
        priority_queue<Pair,vector<Pair>,greater<Pair>> Q;// min-heap
        Q.push(Pair(disDst[dst],dst));
        while(!Q.empty()){
            Pair p = Q.top();
            Q.pop();
            int cur = p.second;
            if(vis[cur]) continue;
            vis[cur] = 1;
            for(int i=1;i<=N;i++){
                if(G[i][cur]==-1) continue;
                if(disDst[cur]+G[i][cur] < disDst[i]){
                    disDst[i] = disDst[cur]+G[i][cur];
                    Q.push(Pair(disDst[i],i));
                }
            }
        }
    }
    
  • 相关阅读:
    【转】c++ http下载文件
    unity事件
    【Unity3D自学记录】判断物体是否在镜头内
    Unity3D研究院之获取摄像机的视口区域
    Unity3D特效-场景淡入淡出
    Unity3D深入浅出
    胶囊碰撞体(CapsuleCollider)
    unity Dotween插件的简单介绍及示例代码
    使用Animation实现摄像机动画
    Unity3D研究院之使用Animation编辑器编辑动画
  • 原文地址:https://www.cnblogs.com/chengyh23/p/14585378.html
Copyright © 2011-2022 走看看