【参考】
本题的题解:
http://www.cnblogs.com/zhj5chengfeng/p/3273531.html
还有那篇平面图网络流的论文:
《两极相通——浅析最大—最小定理在信息学竞赛中的应用》
两篇足够了。
【代码】
#pragma comment<linker,"/STACK:102400000">
#include <cstdio>
#include <cstring>
#include <cctype>
#include <queue>
using namespace std;
#define mp(i,j) make_pair(i,j)
#define fs first
#define sc second
typedef pair<int,int> PairInt;
const int S=2000000;
const int M=6000000;
int n,m;
int sc,sk;
struct Graph
{
int v,d,nxt;
}mp[M];
int tt,hd[S];
inline int read(void)
{
int x=0,f=1; char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
inline void ins(int u,int v,int d)
{
mp[++tt].v=v;
mp[tt].d=d;
mp[tt].nxt=hd[u];
hd[u]=tt;
}
inline int id(int i,int j,int kd)
{
return ((i-1)*(m-1)+j-1)*2+kd;
}
priority_queue<PairInt> q;
int vis[S],dis[S];
int main(void)
{
n=read(),m=read();
if (n<=1&&m<=1) {printf("0\n");return 0;}
int x;
sc=0,sk=(n-1)*(m-1)<<1|1; //from 0 to vtx
for (int i=1;i<=n;i++)
for (int j=1;j<=m-1;j++)
{
x=read();
if (i==1)
ins(sc,id(i,j,1),x),ins(id(i,j,1),sc,x);
else
if (i==n)
ins(id(i-1,j,2),sk,x),ins(sk,id(i-1,j,2),x);
else ins(id(i-1,j,2),id(i,j,1),x),ins(id(i,j,1),id(i-1,j,2),x);
}
for (int i=1;i<=n-1;i++)
for (int j=1;j<=m;j++)
{
x=read();
if (j==1&&j==m)
ins(sc,sk,x),ins(sk,sc,x);
else
if (j==1)
ins(id(i,j,2),sk,x),ins(sk,id(i,j,2),x);
else
if (j==m)
ins(sc,id(i,j-1,1),x),ins(id(i,j-1,1),sc,x);
else ins(id(i,j-1,1),id(i,j,2),x),ins(id(i,j,2),id(i,j-1,1),x);
}
for (int i=1;i<=n-1;i++)
for (int j=1;j<=m-1;j++)
{
x=read();
ins(id(i,j,1),id(i,j,2),x),ins(id(i,j,2),id(i,j,1),x);
}
PairInt now;
memset(vis,0,sizeof vis);
memset(dis,63,sizeof dis);
q.push(mp(0,sc));
for (;!vis[sk];)
{
now=q.top(),q.pop();
if (vis[now.sc]==1) continue;
dis[now.sc]=-now.fs,vis[now.sc]=1;
for (int k=hd[now.sc];k;k=mp[k].nxt)
if (!vis[mp[k].v]&&dis[now.sc]+mp[k].d<dis[mp[k].v])
q.push(mp(now.fs-mp[k].d,mp[k].v));
}
printf("%d\n",dis[sk]);
return 0;
}
【小结】
主要补充的就是这一部分,总结一下平面图网络流的一些要点。
①如何想到用最短路的方法解网络流?
很直接的就能想到,平面图、结构统一利于编号的网络。
②如何编号才能降低出错率?
一般来说,平面图网络流的每一块区域都是矩形的吧。
那就弄个函数
id(i,j)
表示第
i
行,第
然后注意边权与区域的关系。
这个应该不要紧,毕竟我们还可以调试。
③特别注意小数据的特判,特判主要有两个地方要注意:
- 在跑最短路时把特殊情况处理掉;
- 区域连边时若只有
1
行,那么会出现