频道栏目
首页 > 考试 > 其他 > 正文
[最短路 杂题] BZOJ 4356 Ceoi2014 Wall
2017-05-06 09:22:36         来源:雯舞  
收藏   我要投稿

[最短路 杂题] BZOJ 4356 Ceoi2014 Wall。

首先可以证明 这个环必然包裹住了所有左上角到其他城市的最短路

这里写图片描述

证明可以调整为包进去 而不会边劣

然后求出所有最短路 然后把它们包进去的话 把一个交点拆成四个点 然后跑一下左上角绕一圈到左上角的最短路

\

#include

#include

#include

#include

#include

#define cl(x) memset(x,0,sizeof(x))

using namespace std;

typedef long long ll;

typedef pair 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[N],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[N]; int pre[N];

priority_queue,greater > 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[N];

int mark[N][4],del[N];

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;

}

点击复制链接 与好友分享!回本站首页
上一篇:[BEST定理 矩阵树定理] BZOJ 3659 Which Dreamed It
下一篇:循环打印100以内的素数
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站