题解 P3831 【[SHOI2012]回家的路】

wuzhoupei

2018-02-24 15:30:24

Solution

![Peipei](http://img.blog.csdn.net/20180120093509502?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcHJldGVuZF9mYWw=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 还是我的**logo** ^_^ ----- 这个题乍一看像个网络流 然而不是 然后就发现特别像最短路的题 把每一行的点互相连边,每一列同理 每次转移时判断当前点是不是转折点,一次判断是否+1 但是有一点让这道题不像最短路: ### 如果一条线上全是转折点,那岂不是边的条数要达到 # n^2 !!! 但是我们发现有些边是没必要建的,比如 A -> B -> C 那么我们就没必要建一条 A -> C 的边了 所以我们把相邻的建边,spfa 飞过就好了 但是有个小细节,就像 A -> B -> C 中 B 不能算作转折点 在 B 处不 +1 至于如何判断当前点是否为转折点 我们记录当前点的 fa[x] 判断 如果 fa[x] 与 go(即将转移的点) 不共线, 那么 x 就是一个转折点 -------------- ```cpp #include <bits/stdc++.h> #define II int #define IL inline #define R register #define I 423546 using namespace std; IL void of(R II &a) { R char c=getchar (); R II w=1, p=0; while (c<'0' || c>'9') { if(c=='-') w=-1; c=getchar (); } while (c>='0' && c<='9') { p=p*10+c-'0'; c=getchar (); } a=w*p; } /* -------------------- Peipei -------------------- */ II n,m,_tot; II head[I], dis[I], inq[I], fa[I]; queue <II> Q; struct oAo { II x,y,wei; } edge[I]; IL bool maPx(oAo a1,oAo a2) { return a1.x==a2.x ? a1.y<a2.y : a1.x<a2.x ;} IL bool maPy(oAo a1,oAo a2) { return a1.y==a2.y ? a1.x<a2.x : a1.y<a2.y ;} IL bool maPwei(oAo a1,oAo a2) { return a1.wei<a2.wei ;} struct owo { II to,up,w; } aa[I]; IL void add(R II x,R II y,R II z) { aa[++_tot]=(owo) {y,head[x],z}; head[x]=_tot; } IL void spfa() { for(R II i=1;i<=m+1;i++) dis[i]=1e9; Q.push(0); inq[0]=1; dis[0]=0; while (!Q.empty()) { R II x=Q.front(); Q.pop(); inq[x]=0; for(R II i=head[x],go,K;i;i=aa[i].up) { go=aa[i].to; K=(edge[fa[x]].x!=edge[go].x && edge[fa[x]].y!=edge[go].y); if(dis[go]>dis[x]+aa[i].w+K) { dis[go]=dis[x]+aa[i].w+K; if(!inq[go]) Q.push(go), inq[go]=1; fa[go]=x; } } } printf("%d\n",dis[m+1]); exit(0); } int main() { of(n); of(m); for(R II i=1;i<=m;i++) of(edge[i].x), of(edge[i].y), edge[i].wei=i; of(edge[0].x); of(edge[0].y); of(edge[m+1].x); of(edge[m+1].y); edge[m+1].wei=m+1; sort(edge,edge+m+2,maPx); for(R II i=0;i<=m;i++) if(edge[i].x==edge[i+1].x) { add(edge[i].wei,edge[i+1].wei,abs(edge[i].y-edge[i+1].y)*2); add(edge[i+1].wei,edge[i].wei,abs(edge[i].y-edge[i+1].y)*2); } sort(edge,edge+m+2,maPy); for(R II i=0;i<=m;i++) if(edge[i].y==edge[i+1].y) { add(edge[i].wei,edge[i+1].wei,abs(edge[i].x-edge[i+1].x)*2); add(edge[i+1].wei,edge[i].wei,abs(edge[i].x-edge[i+1].x)*2); } sort(edge,edge+m+2,maPwei); spfa(); } ``` ----------