poj2374 Fence Obstacle Course(线段树+建图spfa)

来源:互联网 发布:北师大网络教育登录 编辑:程序博客网 时间:2024/06/05 20:39

从上往下看,每条栅栏只有左右端点有意义,而且从每个点出发只会在一条栅栏处停下,所以每个点最多连两条边。我们可以用线段树维护这个连边操作。(每个点只有第一次被覆盖时连边,然后每次把两个端点加进去)然后从s点再连一下,最后剩的都再和终点连一下,然后跑最短路即可。

#include <cstdio>#include <cstring>#include <algorithm>#include <deque>using namespace std;#define inf 0x3f3f3f3f#define ll long long#define N 50010#define M 200010#define treen 200001inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}int n,s,num=0,h[N<<1],id1,id2,tot=1;ll d[N<<1];bool inq[N<<1];struct node{    int x,id;}tree[M<<2];struct dat{    int x,y;}a[N];struct edge{    int to,next,val;}data[N<<2];inline void add(int x,int y,int val){    data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].val=val;}void build(int p,int l,int r){    if(l==r) return;    int mid=l+r>>1;    build(p<<1,l,mid);build(p<<1|1,mid+1,r);}void solve(int p,int l,int r,int x,int y){    if(tree[p].x==0) return;    if(l==r){        if(id2==id1) add(tree[p].id,id1,abs(l-100001));        else add(tree[p].id,id1,l-x),add(tree[p].id,id2,y-l);        tree[p].x=0;return;    }    int mid=l+r>>1;    if(x<=mid) solve(p<<1,l,mid,x,y);    if(y>mid) solve(p<<1|1,mid+1,r,x,y);    tree[p].x=tree[p<<1].x+tree[p<<1|1].x;}void insert1(int p,int l,int r,int x,int val){    if(l==r){tree[p].x=1,tree[p].id=val;return;}    int mid=l+r>>1;    if(x<=mid) insert1(p<<1,l,mid,x,val);    else insert1(p<<1|1,mid+1,r,x,val);    tree[p].x=tree[p<<1].x+tree[p<<1|1].x;}void spfa(){    deque<int>q;    for(int i=1;i<=tot;++i) d[i]=1LL<<60;d[1]=0;    q.push_back(1);inq[1]=1;    while(!q.empty()){        int x=q.front();q.pop_front();inq[x]=0;        for(int i=h[x];i;i=data[i].next){            int y=data[i].to;            if(d[x]+data[i].val<d[y]){                d[y]=d[x]+data[i].val;                if(!inq[y]){                    if(!q.empty()&&d[y]<d[q.front()]) q.push_front(y);                    else q.push_back(y);inq[y]=1;                }            }        }    }}int main(){//  freopen("a.in","r",stdin);    n=read();s=read()+100001;    build(1,1,treen);    for(int i=1;i<=n;++i){        a[i].x=read()+100001,a[i].y=read()+100001;    }add(1,2,s-a[n].x);add(1,3,a[n].y-s);    for(int i=n;i>=1;--i){        id1=++tot;id2=++tot;        solve(1,1,treen,a[i].x,a[i].y);        insert1(1,1,treen,a[i].x,id1);        insert1(1,1,treen,a[i].y,id2);    }id1=id2=++tot;solve(1,1,treen,1,treen);    spfa();    printf("%lld\n",d[tot]);    return 0;}
原创粉丝点击