#spfa,离散#poj 3171 jzoj 1254 洛谷 4644 清理牛棚 Cleaning Shifts

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sugar_free_mint/article/details/82149172

没有边权的题解poj 2376


题目

poj 2376带边权版


分析

搜到了一份厉害的解题报告, s p f a ,不由得谈最短路色变,可以发现中间点其实是不紧要的,因为如果能跑最短路,那么中间的点一定能被覆盖,关于可能重叠的问题就反向建边权为0的边就行了

  • x > y
  • y > x

看起来好像不行,其实画个图就可以解释清楚
这里写图片描述
如图,上图是无法覆盖的,而下图是可以覆盖的,所以反向边就是为了处理重叠部分,讲到这里,搞搞离散跑最短路就好了


代码

#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
struct node{int x,y,w,next;}e[30001]; std::queue<int>q;
int n,s,t,ls[20001]; std::vector<int>uk;
int in(){
    int ans=0; char c=getchar();
    while (c<48||c>57) c=getchar();
    while (c>47&&c<58) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
    return ans;
}
int main(){
    n=in(); s=in(); t=in()+1;
    for (register int i=1;i<=n;i++){
        e[i].x=in(); e[i].y=in()+1; e[i].w=in();//完全覆盖(所以多增加1避免没有重复部分且完成(使出现重复部分))
        uk.push_back(e[i].x); uk.push_back(e[i].y);
    }
    std::sort(uk.begin(),uk.end());
    int m=std::unique(uk.begin(),uk.end())-uk.begin();//去重
    for (register int i=0;i<m;i++) ls[i]=66666;
    for (register int i=1;i<=n;i++){
        e[i].x=std::lower_bound(uk.begin(),uk.begin()+m,e[i].x)-uk.begin();
        e[i].y=std::lower_bound(uk.begin(),uk.begin()+m,e[i].y)-uk.begin();//离散
        e[i].next=ls[e[i].x]; ls[e[i].x]=i;//建邻接表
    }
    int flag1=0,flag2=0;
    for (register int i=1;i<m;i++) e[n+i]=(node){i,i-1,0,ls[i]},ls[i]=n+i;//反向边
    for (register int i=0;i<m;i++){
        if (uk[i]==s) flag1=i+1;//记录是否存在起、终点
        if (uk[i]==t) flag2=i+1;
    }
    if (!flag1||!flag2) return !printf("-1"); 
    flag1--; flag2--; int dis[m]; bool v[m];
    for (register int i=0;i<m;i++) dis[i]=707406378,v[i]=0;
    q.push(flag1); dis[flag1]=0; v[flag1]=1;
    while (q.size()){//spfa
        int x=q.front(); q.pop();
        for (register int i=ls[x];i!=66666;i=e[i].next)
        if (dis[e[i].y]>dis[x]+e[i].w){
            dis[e[i].y]=dis[x]+e[i].w;
            if (!v[e[i].y]) v[e[i].y]=1,q.push(e[i].y);
        }
        v[x]=0;
    }
    if (dis[flag2]==707406378) return !printf("-1");//找不到最短路
    else return !printf("%d",dis[flag2]);
}

猜你喜欢

转载自blog.csdn.net/sugar_free_mint/article/details/82149172