zoukankan      html  css  js  c++  java
  • ZOJ 3391 Haunted Graveyard(最短路负权回路)题解

    题意:好长...从(0,0)走到(w-1,h-1),墓碑不能走,走到传送门只能进去不能走到其他地方,经过传送门时间会变化w(可能为负),其他地方都能上下左右走。如果能无限返老还童输出Never,走不到终点输出Impossible,其他输出最短时间。

    思路:没想到是最短路,刚看懂题目还以为是暴搜+剪枝,听到无限返老还童是负权回路才想起来可以用最短路spfa来做。这题就是建边跑spfa就行了,建边方法如题意。注意一下建边的时候终点不能为边的起始,这里WA了,因为到终点了就结束了,如果还能走可能会进入负权回路。题目输出的优先级应该是这样的:有never先输出,其次最短路,最后impossible。

    代码:

    #include<set>
    #include<map>
    #include<cstdio>
    #include<utility>
    #include<cmath>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<cstring>
    #include<string>
    #include<sstream>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    #define ull unsigned long long
    using namespace std;
    const int maxn = 900+5;
    const int seed = 131;
    const int MOD = 100013;
    const int INF = 0x3f3f3f3f;
    struct Edge{
        int to,val;
        Edge(int _to = 0,int _val = 0):to(_to),val(_val){}
    };
    vector<Edge> G[maxn];
    int w,h,turn[4][2] = {0,1,0,-1,1,0,-1,0};
    set<int> grave,bh;
    int point(int x,int y){
        return (x - 1) * h + y;
    }
    void addEdge(int u,int v,int val){
        G[u].push_back(Edge(v,val));
    }
    
    bool vis[maxn];
    int cnt[maxn],dist[maxn];
    
    bool spfa(int start,int n){
        memset(vis,false,sizeof(vis));
        for(int i = 0;i <= n;i++) dist[i] = INF;
        vis[start] = true;
        dist[start] = 0;
        queue<int> q;
        while(!q.empty()) q.pop();
        q.push(start);
        memset(cnt,0,sizeof(cnt));
        cnt[start] = 1;
        while(!q.empty()){
            int u = q.front();
            q.pop();
            vis[u] = false;
            for(int i = 0;i < G[u].size();i++){
                int v = G[u][i].to;
                if(dist[v] > dist[u] + G[u][i].val){
                    dist[v] = dist[u] + G[u][i].val;
                    if(!vis[v]){
                        vis[v] = true;
                        q.push(v);
                        if(++cnt[v] > n) return false;
                    }
                }
            }
        }
        return true;
    }
    
    int main(){
        int g,e;
        while(scanf("%d%d",&w,&h) != EOF && w + h){
            grave.clear();
            bh.clear();
            for(int i = 0;i <= point(w,h);i++) G[i].clear();
            scanf("%d",&g);
            while(g--){
                int x,y;
                scanf("%d%d",&x,&y);
                x++,y++;
                grave.insert(point(x,y));
            }
            scanf("%d",&e);
            while(e--){
                int x1,y1,x2,y2,w;
                scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&w);
                x1++,y1++,x2++,y2++;
                addEdge(point(x1,y1),point(x2,y2),w);
                bh.insert(point(x1,y1));
            }
            for(int i = 1;i <= w;i++){
                for(int j = 1;j <= h;j++){
                    int now = point(i,j);
                    if(i == w && j == h) continue;
                    if(grave.count(now)) continue;
                    if(bh.count(now)) continue;
                    for(int k = 0;k < 4;k++){
                        int fx = i + turn[k][0],fy = j + turn[k][1];
                        if(fx < 1 || fx > w || fy < 1 || fy > h) continue;
                        int to = point(fx,fy);
                        if(grave.count(to)) continue;
                        else{
                            addEdge(now,to,1);
                        }
                    }
                }
            }
            bool never;
            never = spfa(point(1,1),point(w,h));
            if(!never){
                printf("Never
    ");
            }
            else{
                if(dist[point(w,h)] >= INF) printf("Impossible
    ");
                else printf("%d
    ",dist[point(w,h)]);
            }
        }
        return 0;
    }
  • 相关阅读:
    生成类似于MongoDB产生的ObjectId
    链式编程:遇到多个构造器参数(Constructor Parameters)时要考虑用构建器(Builder)
    mysql时间字符串按年/月/天/时分组查询 -- date_format
    根据模板导出excel
    九度 1188 约瑟夫环问题
    快速排序
    Linux 命令
    volatile小记
    线程池ThreadPoolExecutor
    CyclicBarrier、CountDownLatch与Semaphore的小记
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9504471.html
Copyright © 2011-2022 走看看