首页 > 其他 > 详细

洛谷 P3036 [USACO16DEC]Lasers and Mirrors激光和镜子

时间:2020-01-27 12:11:50      阅读:83      评论:0      收藏:0      [点我收藏+]

题目链接

以下内容引用自_Yunluo_ 的博客,原文链接

每个点拆成4个

技术分享图片

蓝色虚线的边长度为0,橙色实线的边长度为1

然后再在节点中连边,像下图那样

技术分享图片

最后建一个超级起点和超级终点,超级起点向原起点的四个节点连边(dis=0),原终点的四个节点向超级中电加边(dis=0)

跑最短路

各组节点之间连变的时候,可以分别按照x和y排序后加变

以样例为例:

技术分享图片

引用结束

[Code]

#include<bits/stdc++.h>
using namespace std;

int read(){
    int x=0; char c=getchar(); int flag=1;
    while(!isdigit(c)) { if(c=='-') flag=-1; c=getchar(); }
    while(isdigit(c)) { x=((x+(x<<2))<<1)+(c^48); c=getchar(); }
    return x*flag;
}

const int N=1e6+10;

int n;

struct Node{
    int x,y;
    int id;
}a[N];
bool cmp1(Node a,Node b) { if(a.x==b.x) return a.y<b.y; return a.x<b.x; }
bool cmp2(Node a,Node b) { if(a.y==b.y) return a.x<b.x; return a.y<b.y; }

struct Edge{
    int to,next,v;
}edge[N<<4];
int head[N<<2];
int tmp=0;

void add(int x,int y,int z){
    ++tmp;
    edge[tmp].to=y; edge[tmp].next=head[x]; edge[tmp].v=z;
    head[x]=tmp;
}

void Add_edge(int x,int y,int z){
    add(x,y,z); add(y,x,z);
}

int dep[N];

signed main(){
    memset(head,-1,sizeof(head));
    n=read();
    a[0].x=read(); a[0].y=read(); a[0].id=0;
    a[n+1].x=read(); a[n+1].y=read(); a[n+1].id=n+1;//存入汇点,源点
    for(int i=1;i<=n;i++){
        a[i].x=read();a[i].y=read();a[i].id=i;
    }
    
    sort(a,a+n+2,cmp1);//按照x坐标排序
    
    for(int i=0;i<=n;i++){//在x坐标相同的之间连边
        if(a[i].x==a[i+1].x){
            Add_edge((a[i].id<<2)+3,(a[i+1].id<<2)+2,0);
        }
    }
    
    sort(a,a+n+2,cmp2); //按照y坐标排序
    
    for(int i=0;i<=n;i++){//在y坐标相同的之间连边
        if(a[i].y==a[i+1].y){
            Add_edge((a[i].id<<2)+4,(a[i+1].id<<2)+1,0);
        }
    }
    
    for(int i=0;i<=n;i++){//在拆点的四个点之间连边
        Add_edge((a[i].id<<2)+1,(a[i].id<<2)+2,1);
        Add_edge((a[i].id<<2)+1,(a[i].id<<2)+3,1);
        Add_edge((a[i].id<<2)+1,(a[i].id<<2)+4,0);
        Add_edge((a[i].id<<2)+2,(a[i].id<<2)+3,0);
        Add_edge((a[i].id<<2)+2,(a[i].id<<2)+4,1);
        Add_edge((a[i].id<<2)+3,(a[i].id<<2)+4,1);
    }
    
    memset(dep,-1,sizeof(dep));
    queue<int> q;
    dep[1]=dep[2]=dep[3]=dep[4]=0;
    q.push(1); q.push(2); q.push(3); q.push(4);//跑最短路,实际上应该是0/1 bfs
    
    while(!q.empty()){
        int f=q.front(); q.pop();
        for(int i=head[f];i!=-1;i=edge[i].next){
            int t=edge[i].to;
            if(dep[t]!=-1) continue;
            dep[t]=dep[f]+edge[i].v;
            q.push(t);
        }
    }
    
    printf("%d\n",min(min(dep[4*n+5],dep[4*n+6]),min(dep[4*n+7],dep[4*n+8])));//答案
    return 0;
}

洛谷 P3036 [USACO16DEC]Lasers and Mirrors激光和镜子

原文:https://www.cnblogs.com/zzhzzh123/p/12235580.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!