狼抓兔子
明显的最小割,但数据范围比较大(虽然据讨论可以水过但我没去试)。于是考虑使用正确复杂度的算法,想到对偶图。然后这就是一个对偶图的板子了,图都给你画出来了正常加边跑最短路即可。需要注意的是加边的时候要加无向边,在这个地方卡了一会。每日维生素B。
#include<bits/stdc++.h>
//#define feyn
const int N=1010;
const int M=N*N*2;
using namespace std;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
struct edge{
int t,v,next;
}e[M<<2];
int esum,head[M];
inline void adde(int fr,int to,int val){
e[++esum]=(edge){to,val,head[fr]};head[fr]=esum;
}
inline void add(int fr,int to,int val){
adde(fr,to,val);adde(to,fr,val);
}
struct node{
int pl,dis;
};
inline bool operator <(node s1,node s2){
return s2.dis<s1.dis;
}
priority_queue<node>q;
int dis[M];
int m,n,in;
int cnt,ss,tt,a[N][N][2];
signed main(){
#ifdef feyn
freopen("in.txt","r",stdin);
#endif
read(m);read(n);
ss=++cnt;tt=++cnt;
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
a[i][j][0]=++cnt;
a[i][j][1]=++cnt;
}
}
for(int i=1;i<=m;i++){
for(int j=1;j<n;j++){
read(in);
if(i==1)add(a[i][j][1],tt,in);
else if(i==m)add(ss,a[i-1][j][0],in);
else add(a[i][j][1],a[i-1][j][0],in);
}
}
for(int i=1;i<m;i++){
for(int j=1;j<=n;j++){
read(in);
if(j==1)add(ss,a[i][j][0],in);
else if(j==n)add(a[i][j-1][1],tt,in);
else add(a[i][j-1][1],a[i][j][0],in);
}
}
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
read(in);
add(a[i][j][0],a[i][j][1],in);
}
}
memset(dis,0x3f,sizeof(dis));
dis[ss]=0;q.push((node){ss,0});
while(!q.empty()){
node now=q.top();q.pop();
int wh=now.pl,nd=now.dis;
if(nd>dis[wh])continue;
for(int i=head[wh],th;i;i=e[i].next){
int now_d=dis[wh]+e[i].v;
if(now_d>=dis[th=e[i].t])continue;
dis[th]=now_d;q.push((node){th,dis[th]});
}
}
printf("%d\n",dis[tt]);
return 0;
}
一如既往,万事胜意