【Bzoj】1001狼抓兔子(平面图最小割转对偶图最短路)
YEAH
终于做对这道题啦 建图的艰辛难以言表- -
顺便说一句我队列转STL啦
狼抓兔子的地图符合平面图定义,于是将该图转成对偶图并求出对偶图的最短路即可。
这篇博客给了我极大的帮助,现将链接放上
粘上自己的代码
#include<cstdio> #include<cstdlib> #include<cctype> #include<cstring> #include<cmath> #include<algorithm> #include<queue> using namespace std; queue<int> q; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } struct Edge{ int next,to,val; }edge[6000020]; int head[2000020],num; inline void add(int from,int to,int val){ edge[++num]=(Edge){head[from],to,val}; head[from]=num; } int disa[1002][1002],disb[1002][1002],id[1002][1002][3]; int ID,Start,End; bool vis[2000200]; int dst[2000200]; int main(){ memset(dst,127/3,sizeof(dst)); int n=read(),m=read(); End=n*m+1; for(int i=1;i<=n;++i) for(int j=1;j<m;++j) disa[i][j]=read(); for(int i=1;i<n;++i) for(int j=1;j<=m;++j) disb[i][j]=read(); if(n==1){ int a=0x7fffffff; for(int i=1;i<m;++i) a=min(a,disa[1][i]); printf("%d",a); return 0; } if(m==1){ int a=0x7fffffff; for(int i=1;i<n;++i) a=min(a,disb[i][1]); printf("%d",a); return 0; } for(int i=1;i<n;++i) for(int j=1;j<m;++j){ int x=read(); id[i][j][1]=++ID; id[i][j][2]=++ID; add(id[i][j][1],id[i][j][2],x); add(id[i][j][2],id[i][j][1],x); } for(int i=1;i<n;++i){ add(Start,id[i][1][1],disb[i][1]); add(id[i][1][1],Start,disb[i][1]); add(id[i][m-1][2],End,disb[i][m]); add(End,id[i][m-1][2],disb[i][m]); } for(int i=1;i<n;++i) for(int j=1;j<m-1;++j){ add(id[i][j][2],id[i][j+1][1],disb[i][j+1]); add(id[i][j+1][1],id[i][j][2],disb[i][j+1]); } for(int i=1;i<m;++i){ add(Start,id[n-1][i][1],disa[n][i]); add(id[n-1][i][1],Start,disa[n][i]); add(id[1][i][2],End,disa[1][i]); add(End,id[1][i][2],disa[1][i]); } for(int i=1;i<n-1;++i) for(int j=1;j<m;++j){ add(id[i][j][1],id[i+1][j][2],disa[i+1][j]); add(id[i+1][j][2],id[i][j][1],disa[i+1][j]); } q.push(Start);dst[Start]=0; while(!q.empty()){ int from=q.front();vis[from]=0;q.pop(); for(int i=head[from];i;i=edge[i].next){ int to=edge[i].to; if(dst[to]>dst[from]+edge[i].val){ dst[to]=dst[from]+edge[i].val; if(vis[to]) continue; vis[to]=1; q.push(to); } } } printf("%d",dst[End]); return 0; }