P4001 [BJOI2006]狼抓兔子
70分:
最小割=最大流
不会卡常,告辞
// luogu-judger-enable-o2
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cctype>
using namespace std;
#define rg register
#define il inline
#define sta static
#define vd void
il int gi(){
sta int x,flg;sta char ch;
x=flg=0,ch=getchar();
while(!isdigit(ch)){if(ch=='-')flg=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return flg?-x:x;
}
int id[1001][1001],S,T;
const int maxn=1000001,maxm=maxn*6+233;
int dep[maxn],fir[maxn],dis[maxm],nxt[maxm],w[maxm],ID=1;
il vd link(const int&x,const int&y,const int&z){
nxt[++ID]=fir[x],fir[x]=ID,dis[ID]=y,w[ID]=z;
nxt[++ID]=fir[y],fir[y]=ID,dis[ID]=x,w[ID]=z;
}
il bool BFS(){
sta int que[maxn],hd=0,tl=0;
for(rg int i=0;i^tl;++i)dep[que[i]]=-1;
hd=tl=0;que[tl++]=S;dep[S]=1;
while(hd^tl){
sta int x;x=que[hd++];
for(rg int i=fir[x];i;i=nxt[i])
if(w[i]&&dep[dis[i]]==-1)dep[dis[i]]=dep[x]+1,que[tl++]=dis[i];
}
return ~dep[T];
}
il int Dinic(const int&x,int maxflow){
if(x==T)return maxflow;
int ret=0,d;
for(rg int i=fir[x];i;i=nxt[i])
if(w[i]&&dep[dis[i]]==dep[x]+1){
d=Dinic(dis[i],min(w[i],maxflow-ret));
ret+=d,w[i]-=d,w[i^1]+=d;
if(ret==maxflow)return ret;
}
return ret;
}
int main(){
int n=gi(),m=gi();
for(rg int i=1;i<=n;++i)
for(rg int j=1;j<=m;++j)
id[i][j]=++id[0][0];
for(rg int i=1;i<=n;++i)
for(rg int j=1;j<m;++j)
link(id[i][j],id[i][j+1],gi());
for(rg int i=1;i<n;++i)
for(rg int j=1;j<=m;++j)
link(id[i][j],id[i+1][j],gi());
for(rg int i=1;i<n;++i)
for(rg int j=1;j<m;++j)
link(id[i][j],id[i+1][j+1],gi());
int ans=0;
S=id[1][1],T=id[n][m];
for(rg int i=1;i<=id[n][m];++i)dep[i]=-1;
while(BFS())ans+=Dinic(S,2e9);
printf("%d\n",ans);
return 0;
}
100分:平面图转对偶图
不管A,B开头的点,这就是题目里的图,而且是个平面图
平面图就是可以搞成没有边相交的图(广告,ubuntu下平面图转对偶图练习:untangle
然后每个面建一个点,两个面有相交就连接两个面,边权为相交的边的权
如图红边组成对偶图
下面是结论:平面图最小割=对偶图最短路
(当然平面图最短路=对偶图最小割)
注意,平面图要求最小割必须再假装平面图的S-T(1-9)之间有一条边(又粗又黑的边)
然后这条边里面建一个S,另一半建个T就可以建图了
(这个题的图比较优秀 一般图怎么求对偶图呢 我也不知道)
然后用Dijk跑坠短路
(还有需要特判S=T的)
#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il int gi(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
int A[1001][1001],B[1001][1001];
const int maxn=2000010,maxm=1000001*6;
int fir[maxn],nxt[maxm],dis[maxm],w[maxm],S,T,ID;
il vd link(int x,int y,int z){
static int id=0;
nxt[++id]=fir[x];fir[x]=id;dis[id]=y;w[id]=z;
nxt[++id]=fir[y];fir[y]=id;dis[id]=x;w[id]=z;
}
struct Queue{
struct node{int x,y;}a[maxn];
int siz,pos[maxn];
#define fa (x>>1)
#define ls (x<<1)
#define rs (x<<1|1)
il vd Swap(int x,int y){
std::swap(pos[a[x].y],pos[a[y].y]);
std::swap(a[x],a[y]);
}
il vd pushup(int x){
while(x!=1)
if(a[x].x<a[fa].x)Swap(x,fa),x=fa;
else break;
}
il vd pushdown(int x){
while(ls<=siz){
if(ls==siz||a[ls].x<a[rs].x){
if(a[ls].x<a[x].x)Swap(x,ls),x=ls;
else break;
}else{
if(a[rs].x<a[x].x)Swap(x,rs),x=rs;
else break;
}
}
}
il int top(){return a[1].y;}
il vd pop(){Swap(1,siz--);pushdown(1);}
il vd change(int x,int y){
x=pos[x];
a[x].x=y;
pushup(x);
}
il vd clear(int n){
siz=n;for(int i=1;i<=n;++i)a[i]=(node){1e9,i},pos[i]=i;
a[1]=(node){0,1};
}
#undef fa
#undef ls
#undef rs
}que;
int dist[maxn];
bool vis[maxn];
il vd Dij(){
memset(dist,63,sizeof dist);
dist[S]=0;que.clear(ID);
while(que.siz){
int x=que.top();
for(int i=fir[x];i;i=nxt[i]){
if(dist[dis[i]]>dist[x]+w[i]){
dist[dis[i]]=dist[x]+w[i];
que.change(dis[i],dist[dis[i]]);
}
}
que.pop();
}
printf("%d\n",dist[T]);
}
int main(){
freopen("bjrabbit.in","r",stdin);
freopen("bjrabbit.out","w",stdout);
int n=gi(),m=gi();
if(n==1||m==1){
int ans=1e9;
for(int i=1;i<std::max(n,m);++i)ans=std::min(ans,gi());
printf("%d\n",ans);
return 0;
}
S=++ID,T=++ID;
for(int i=1;i<n;++i)
for(int j=1;j<m;++j)
A[i][j]=++ID;
for(int i=1;i<n;++i)
for(int j=1;j<m;++j)
B[i][j]=++ID;
for(int i=1;i<m;++i)link(S,B[1][i],gi());
for(int i=1;i<n-1;++i)
for(int j=1;j<m;++j)
link(A[i][j],B[i+1][j],gi());
for(int i=1;i<m;++i)link(A[n-1][i],T,gi());
for(int i=1;i<n;++i){
link(A[i][1],T,gi());
for(int j=1;j<m-1;++j)
link(B[i][j],A[i][j+1],gi());
link(S,B[i][m-1],gi());
}
for(int i=1;i<n;++i)
for(int j=1;j<m;++j)
link(A[i][j],B[i][j],gi());
Dij();
return 0;
}