1001: [BeiJing2006]狼抓兔子(传送门)
图论新知识。。没学过。。
平面图最小割等于对偶图的最短路
详见课件:http://wenku.baidu.com/view/8f1fde586edb6f1aff001f7d.html
建议下载 直接在百度看可能有重叠 周冬神犇这个课件的演示很清楚。。
动画效果一看就明确了
代码中的建模方式见图:
/**************************************************************
Problem: 1001
User: Lytning
Language: C++
Result: 正确
Time:5212 ms
Memory:161432 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N=3000000+5,M=8000000+5;
struct edge{int u,v,dis; edge *next;}e[M],*point[N],*P=e;
int used[N],d[N],n,m,S=0,T=1;
queue <int> Qe;
inline void add_edge(int a,int b,int dis)
{
//cout<<"edge added : from "<<a<<" to "<<b<<" dis "<<dis<<endl;
edge *Q = ++P; ++P;
P->u = a; P->v = b; P->dis = dis; P->next = point[a]; point[a] = P;
Q->u = b; Q->v = a; Q->dis = dis; Q->next = point[b]; point[b] = Q;
}
void SPFA(int s)
{
memset(d,0x7f,sizeof(d));
memset(used,0,sizeof(used));
Qe.push(s);
used[s]=true;
d[s]=0;
while(!Qe.empty())
{
int x = Qe.front();
Qe.pop();
used[x] = false;
for(edge *j = point[x]; j; j = j->next)
{
if(d[x] + j->dis < d[j->v])
{
d[j->v] = d[x] + j->dis;
if(!used[j->v])
{
used[j->v]=true;
Qe.push(j->v);
}
}
}
}
}
inline int number(int x,int y,bool up)//每一个方格以左上角坐标表示
{
int ret = ((m-1)*(x-1)+y-1)*2+1;
if(up) ret++;
return ret+1; // S:0 T:1
}
/*
平面数 : (n-1)*(m-1) *2
*/
int main()
{
//freopen("bz1001.in","r",stdin);freopen("bz1001.out","w",stdout);
cin>>n>>m;
if(n==1 || m==1)
{
int ans=0;
if(n>m) m=n;
for(int z=1; z<m; z++)
{
if(z==1) cin>>ans;
int t; cin>>t;
if(t<ans) ans =t;
}
cout<<ans<<endl;
}else{
//横向
for(int x=1; x<=n; x++)
{
for(int y=1; y<m; y++)
{
int t; cin>>t;
if(x==1)
add_edge(number(x,y,true),S,t);
else if (x==n)
add_edge(number(x-1,y,false),T,t);
else
add_edge(number(x,y,true),number(x-1,y,false),t);
}
}
//纵向
for(int x=1; x<n; x++)
{
for(int y=1; y<=m; y++)
{
int t; cin>>t;
if(y==1)
add_edge(number(x,y,false),T,t);
else if(y==m)
add_edge(number(x,y-1,true),S,t);
else
add_edge(number(x,y-1,true),number(x,y,false),t);
}
}
//斜
for(int x=1; x<n; x++)
{
for(int y=1; y<m; y++)
{
int t; cin>>t;
add_edge(number(x,y,false),number(x,y,true),t);
}
}
SPFA(S);
cout<<d[T]<<endl;}
}