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


    题目链接

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

    每个点拆成4个

    img

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

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

    img

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

    跑最短路

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

    以样例为例:

    img

    引用结束

    [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
    ",min(min(dep[4*n+5],dep[4*n+6]),min(dep[4*n+7],dep[4*n+8])));//答案
        return 0;
    }
    
    
  • 相关阅读:
    每日一道面试题-02
    JAVA获取对象的四种方式
    每日一道面试题-01
    MD5算法原理浅谈
    JAVA--时间格式转换
    数据库-union和union all
    Struts1和Struts2的区别
    Java定时器Timer
    webView调试
    webView和js交互规范
  • 原文地址:https://www.cnblogs.com/zzhzzh123/p/12235580.html
Copyright © 2020-2023  润新知