Description
圆蛋节到来,学校又开始短暂的放假了,大部分人们都很欢乐。虽然不知道OIER们心情是否很愉快,可以确定的是ACMER们确实放假了, 所以他们脸上充满了笑容,终于有时间集体开黑刷水题了,然后集体开黑放羊去。
与此同时,NAOCAN_HELLIS发现了一个很恼火的现象,当大家沉醉于集体开黑的时候,学校的渣渣网络变得异常的卡。然后,NAOCAN_HELLIS发现了一个更恼火的问题,在此等危急存亡的时刻,有一个重要文件需要通过网络传送给某PLMM。
网络可以简单地n*m的节点组成,例如下面2*4的网络,
Rij 和Dij 为某网络中的传输速度,R和D的方向是固定的,R向右,D向下。而且网络中的边不会有缺,如上图所示。整个网络可以同时工作,边的传输速度决定单位时间内通过该边的流量。并且当一个网络的以最大传输速度工作时,从S到end的单位流量为W,那么不可能还有流量可以从S传输到end。
现在NAOCAN_HELLIS现在想知道网络的最大传输速度是多少。
Input
多组测试数据。每组测试数据格式为:
第一行2个整数n,m。其中0<n,m<=100。
接下来是n *(m-1)的矩阵表示Rij
其中0 < Rij <=10000
接下来是(n -1)*m的矩阵表示Dij
其中0 < Dij <=10000
Output
每组测试数据输出包含一行1个整数,即网络最大传输速度。
Sample Input
2 2
4
1
2 4
5 5
4 15 15 10
4 7 16 7
5 5 15 26
15 22 6 2
6 6 11 11
7 3 15 2 5
14 23 15 20 11
6 12 11 8 5
9 13 10 13 12
Sample Output
5
11
Hint
测试数据不超过200组。注意优化。
【分析】
很明显是平面图网络流,我们采用重新建图后求最短路的方法。
如图:
我们将原图的起点终点用一个虚拟的线连起来。在新图中,每个点对应原图的一个区域,我们定义Sta,End,即起点终点如图所示。然后对节点连边,红色边的权值为所割边的流量,蓝色边的权值为0。
【代码】
/**************************
ID:Ciocio
LANG:C++
DATE:2013-12-04
TASK:Secret
**************************/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <utility>
#include <functional>
#include <vector>
#include <map>
using namespace std;
#define MAXM 60000
#define loc(x,y) ((x-1)*(M-1)+y)
#define pii pair<int,int>
#define m_p make_pair
int N,M,Sta,End;
int dis[MAXM];
bool vis[MAXM];
struct Edge{
int v,d;
Edge *Next;
}E[MAXM];
void _read(int &x)
{
char tt=getchar();
while(tt<'0'||'9'<tt) tt=getchar();
for(x=0;'0'<=tt&&tt<='9';x=(x<<3)+(x<<1)+tt-'0',tt=getchar());
}
Edge *tot;
Edge *Last[MAXM];
inline void _addedge(int u,int v,int d)
{
Edge *p=++tot;
p->v=v;
p->d=d;
p->Next=Last[u];
Last[u]=p;
}
void _init()
{
int Cost;
for(int i=1;i<=N;i++) //重建图
for(int j=1;j<M;j++)
{
_read(Cost);
if(i==1)
_addedge(loc(1,j),End,Cost);
else if(i==N)
_addedge(Sta,loc(N-1,j),Cost);
else
{
_addedge(loc(i-1,j),loc(i,j),0);
_addedge(loc(i,j),loc(i-1,j),Cost);
}
}
for(int i=1;i<N;i++)
for(int j=1;j<=M;j++)
{
_read(Cost);
if(j==1)
_addedge(Sta,loc(i,1),Cost);
else if(j==M)
_addedge(loc(i,M-1),End,Cost);
else
{
_addedge(loc(i,j),loc(i,j-1),0);
_addedge(loc(i,j-1),loc(i,j),Cost);
}
}
}
priority_queue <pii,vector<pii>,greater<pii> > PQ;
void _solve()
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
while(!PQ.empty()) PQ.pop();
dis[Sta]=0;
PQ.push(m_p(dis[Sta],Sta));
while(!PQ.empty())
{
int u;
do u=PQ.top().second,PQ.pop();
while(vis[u]);
if(u==End) break; //重要优化
vis[u]=true;
for(Edge *p=Last[u];p;p=p->Next)
{
int v=p->v,d=p->d;
if((!vis[v])&&(dis[v]>dis[u]+d))
{
dis[v]=dis[u]+d;
PQ.push(m_p(dis[v],v));
}
}
}
cout<<dis[End]<<endl;
}
int main()
{
while(scanf("%d%d",&N,&M)!=EOF)
{
Sta=0;End=(N-1)*(M-1)+1;
tot=&E[0];
for(int i=Sta;i<=End;i++) Last[i]=NULL; //注意初始化
_init();
_solve();
}
return 0;
}