洛谷 P3036 [USACO16DEC]Lasers and Mirrors激光和镜子
以下内容引用自_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;
}