[SPFA]JZOJ 3086 回家
分析
看到换站要1单位时间就想到了网络流……的建图
我们把可以换乘的点拆成一条边就行了
跑SPFA轻松解决
#include <iostream> #include <cstdio> #include <algorithm> #include <queue> using namespace std; const int N=2e4+10; const int M=1e5+10; struct Edge { int u,v,w,nx; }g[10*M]; int cnt,list[2*M],d[2*M]; bool b[2*M]; struct Point { int x,y,id; }a[M],s,t; int n,m; bool CMP1(Point a,Point b) { return a.x<b.x||a.x==b.x&&a.y<b.y; } bool CMP2(Point a,Point b) { return a.y<b.y||a.y==b.y&&a.x<b.x; } void Add(int u,int v,int w) { g[++cnt]=(Edge){u,v,w,list[u]};list[u]=cnt; g[++cnt]=(Edge){v,u,w,list[v]};list[v]=cnt; } void SPFA(int v0) { queue<int> q; while (!q.empty()) q.pop(); for (int i=1;i<=2*m+4;i++) d[i]=2147483647; d[v0]=0;b[v0]=1; q.push(v0); while (!q.empty()) { int u=q.front();q.pop(); for (int i=list[u];i;i=g[i].nx) if (d[g[i].v]>d[u]+g[i].w) { d[g[i].v]=d[u]+g[i].w; if (!b[g[i].v]) q.push(g[i].v); b[g[i].v]=1; } b[u]=0; } } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) scanf("%d%d",&a[i].x,&a[i].y),a[i].id=i,Add(a[i].id,a[i].id+m+2,1); scanf("%d%d%d%d",&s.x,&s.y,&t.x,&t.y);s.id=m+1;t.id=m+2;Add(m+1,2*m+3,0);Add(m+2,2*m+4,0);a[m+1]=s;a[m+2]=t; sort(a+1,a+m+3,CMP1); for (int i=1;i<m+2;i++) if (a[i].x==a[i+1].x) Add(a[i].id,a[i+1].id,2*(a[i+1].y-a[i].y)); sort(a+1,a+m+3,CMP2); for (int i=1;i<m+2;i++) if (a[i].y==a[i+1].y) Add(a[i].id+m+2,a[i+1].id+m+2,2*(a[i+1].x-a[i].x)); SPFA(m+1); printf("%d\n",d[m+2]==2147483647?-1:d[m+2]); }
在日渐沉没的世界里,我发现了你。