您的位置:首页 > 其它

[BJOI2006][bzoj1001] 狼抓兔子 [最小割]

2018-02-21 20:51 288 查看
题面:

传送门

思路:

其实就是一道最小割的题目......

我的写法加了两个优化,常数比较小,所以过掉了

一个是当前弧,一个是若当前点并不能流出去,那么标记dep为-1

听说正解是对偶图最短路?可以找时间学一学......

Code:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define inf 1e9
#define id(i,j) (i-1)*m+j
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
int n,m,cnt=-1,ans,first[1000010],dep[1000010],cur[1000010];
int q[1000010],head,tail;
struct edge{
int to,next,cap;
}a[6000010];
inline void add(int u,int v,int cap){
a[++cnt]=(edge){v,first[u],cap};first[u]=cnt;
a[++cnt]=(edge){u,first[v],cap};first[v]=cnt;
}
bool bfs(int s,int t){
int i,u,v;
head=0,tail=1;q[0]=s;
for(i=s;i<=t;i++) dep[i]=-1,cur[i]=first[i];
dep[s]=1;
while(head<tail){
u=q[head++];
for(i=first[u];~i;i=a[i].next){
v=a[i].to;
if(~dep[v]||(!a[i].cap)) continue;
dep[v]=dep[u]+1;
q[tail++]=v;
}
}
return ~dep[t];
}
int dfs(int u,int t,int limit){
if(u==t||!limit) return limit;
int i,v,f,flow=0;
for(i=cur[u];~i;i=a[i].next){
v=a[i].to;cur[u]=i;//优化一
if(dep[v]==dep[u]+1&&a[i].cap>0){
f=dfs(v,t,min(limit,a[i].cap));
if(f){
flow+=f;limit-=f;
a[i].cap-=f;a[i^1].cap+=f;
if(!limit) return flow;
}
else{
dep[v]=-1;continue;//优化二
}
}
}
return flow;
}
void dinic(int s,int t){
int tmp;
while(bfs(s,t)){
while(tmp=dfs(s,t,inf)) ans+=tmp;
}
}
int main(){
memset(first,-1,sizeof(first));
int i,j,t1;
n=read();m=read();
for(i=1;i<=n;i++){
for(j=1;j<m;j++){
t1=read();
add(id(i,j),id(i,j+1),t1);
}
}
for(i=1;i<n;i++){
for(j=1;j<=m;j++){
t1=read();
add(id(i,j),id(i+1,j),t1);
}
}
for(i=1;i<n;i++){
for(j=1;j<m;j++){
t1=read();
add(id(i,j),id(i+1,j+1),t1);
}
}
dinic(1,n*m);
printf("%d",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: