[最短路 杂题] BZOJ 4356 Ceoi2014 Wall
2017-05-06 07:09
197 查看
具体看题解 我说不清楚
首先可以证明 这个环必然包裹住了所有左上角到其他城市的最短路
证明可以调整为包进去 而不会边劣
然后求出所有最短路 然后把它们包进去的话 把一个交点拆成四个点 然后跑一下左上角绕一圈到左上角的最短路
首先可以证明 这个环必然包裹住了所有左上角到其他城市的最短路
证明可以调整为包进去 而不会边劣
然后求出所有最短路 然后把它们包进去的话 把一个交点拆成四个点 然后跑一下左上角绕一圈到左上角的最短路
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<queue> #define cl(x) memset(x,0,sizeof(x)) using namespace std; typedef long long ll; typedef pair<ll,int> abcd; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=402*402*4+5; const int M=N*4; struct edge{ int u,v,w,next; }G[M]; int head ,inum; inline void add(int u,int v,int w,int p){ G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p; } inline void link(int u,int v,int w){ add(u,v,w,++inum); add(v,u,w,++inum); } #define V G[p].v const int _N=405; int n,m; int a[_N][_N],b[_N][_N],c[_N][_N]; int tot; ll dis ; int pre ; priority_queue<abcd,vector<abcd>,greater<abcd> > Q; inline void Dij(int S){ for (int i=1;i<=tot;i++) dis[i]=1LL<<60,pre[i]=0; dis[S]=0; Q.push(abcd(0,S)); while (!Q.empty()){ abcd t=Q.top(); Q.pop(); int u=t.second; if (dis[u]!=t.first) continue; for (int p=head[u];p;p=G[p].next) if (dis[V]>dis[u]+G[p].w) pre[V]=u,Q.push(abcd(dis[V]=dis[u]+G[p].w,V)); } } #define P(x,y) ((m+1)*((x)-1)+(y)) #define PP(x,y,z) ((P(x,y)-1)*4+z+1) int vst ; int mark [4],del ; inline void Link(int u,int v,int w){ if (del[u] || del[v]) return; link(u,v,w); } inline void dfs(int u){ if (u==1 || vst[u]) return; vst[u]=1; if (pre[u]==u-1) mark[u][3]=mark[pre[u]][1]=1; if (pre[u]==u+1) mark[u][1]=mark[pre[u]][3]=1; if (pre[u]==u-m-1) mark[u][0]=mark[pre[u]][2]=1; if (pre[u]==u+m+1) mark[u][2]=mark[pre[u]][0]=1; dfs(pre[u]); } int main(){ freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(m); tot=(n+1)*(m+1); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) read(a[i][j]); for (int i=1;i<=n;i++) for (int j=1;j<=m+1;j++) read(b[i][j]),link(P(i,j),P(i+1,j),b[i][j]); for (int i=1;i<=n+1;i++) for (int j=1;j<=m;j++) read(c[i][j]),link(P(i,j),P(i,j+1),c[i][j]); Dij(1); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (a[i][j]) dfs(P(i,j)); cl(head); inum=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (a[i][j]) del[PP(i,j,2)]=del[PP(i+1,j,1)]=del[PP(i,j+1,3)]=del[PP(i+1,j+1,0)]=1; del[1]=1; for (int i=1;i<=n+1;i++) for (int j=1;j<=m+1;j++) for (int k=0;k<4;k++) if (!mark[P(i,j)][k]) Link(PP(i,j,k),PP(i,j,(k+1)%4),0); for (int i=1;i<=n;i++) for (int j=1;j<=m+1;j++) Link(PP(i,j,3),PP(i+1,j,0),b[i][j]),Link(PP(i,j,2),PP(i+1,j,1),b[i][j]); for (int i=1;i<=n+1;i++) for (int j=1;j<=m;j++) Link(PP(i,j,1),PP(i,j+1,0),c[i][j]),Link(PP(i,j,2),PP(i,j+1,3),c[i][j]); tot<<=2; Dij(2); printf("%lld\n",dis[4]); /*int t=4; while (t) printf("%d\n",t),t=pre[t];*/ return 0; }
相关文章推荐
- [bzoj4356][ceoi2014] wall
- BZOJ 4356 Ceoi2014 Wall
- BZOJ4356 : Ceoi2014 Wall
- Ceoi2014 bzoj 4356 考托福又不会考 国家集训队作业题
- CEOI 2014 wall (最短路)
- |BZOJ 3445|最短路|[Usaco2014 Feb] Roadblock
- bzoj 3575: [Hnoi2014]道路堵塞 最短路
- bzoj 4364: [IOI2014]wall砖墙 线段树
- [BZOJ]4364: [IOI2014]wall砖墙 线段树
- bzoj 4364: [IOI2014]wall砖墙
- BZOJ 4152: [AMPPZ2014]The Captain(最短路)
- BZOJ4144 [AMPPZ2014]Petrol 【最短路 + 最小生成树】
- bzoj 4364: [IOI2014]wall砖墙
- BZOJ 4144: [AMPPZ2014]Petrol 最短路+最小生成树+倍增
- 【BZOJ3875】[Ahoi2014]骑士游戏【最短路】【DP】
- bzoj3445[Usaco2014 Feb] Roadblock 最短路(记录路径)
- bzoj 1665: [Usaco2006 Open]The Climbing Wall 攀岩(最短路)
- bzoj 4144 [AMPPZ2014]Petrol 最短路+最小生成树+倍增
- BZOJ 4152: [AMPPZ2014]The Captain 分层图最短路
- BZOJ 4016: [FJOI2014]最短路径树问题( 最短路 + 点分治 )