tema
Conejo garra de lobo
http://www.lydsy.com/JudgeOnline/problem.php?id=1001
análisis
Parece estar buscando un corte mínimo, ¿intenta construir un buen gráfico usando flujo de red?
Entregué TLE por primera vez, intenté optimizarlo y se acabó. (Para obtener más información, consulte la función find ())
programa
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define For(x) for(int h=head[x]; h; h=E[h].nxt)
#define V (E[h].v)
#define R (E[h].cap-E[h].flow)
struct Edge{
int v,cap,flow,nxt;} E[6000000];
int num,n,m,S,T,k,l,r,ans;
int head[3000005],dis[3000005],q[3000005];
void add(int u,int v){
scanf("%d",&k);
E[++num]=(Edge){v,k,0,head[u]}; head[u]=num;
E[++num]=(Edge){u,k,0,head[v]}; head[v]=num;
}
void init(){
scanf("%d%d",&n,&m);
S=0,T=n*m-1,num=1;
for (int i=0; i<n; i++)
for (int j=0; j<m-1; j++)
add(i*m+j,i*m+j+1);
for (int i=0; i<n-1; i++)
for (int j=0; j<m; j++)
add(i*m+j,(i+1)*m+j);
for (int i=0; i<n-1; i++)
for (int j=0; j<m-1; j++)
add(i*m+j,(i+1)*m+j+1);
}
bool bfs(){
memset(dis,0,sizeof(dis));
dis[S]=1;
for (q[l=r=0]=S; l<=r; l++){
For(q[l]) if (!dis[V] && R>0){ // V 还没分过层,且 u->v 还有残余流量,说明可用
dis[V]=dis[q[l]]+1;
q[++r]=V;
}
}
if (dis[T]) return 1; //还有增广路
return 0;
}
int find(int x,int low){
if (x==T) return low;
int a,tmp=0; //tmp:经过 x 节点,最多能增加的流
For(x) if (dis[V]==dis[x]+1 && R>0){ //一条可行的弧
a=find(V,min(low-tmp,R));
E[h].flow+=a; //正向边
E[h^1].flow-=a; //反向边
tmp+=a;
if (low==tmp) return tmp; else dis[V]=-1; //加了这一句,以便在已经满流的情况下不再讨论了。
}
return tmp;
}
void debug(){
for (int i=0; i<n; i++)
for (int j=0; j<m; j++){
printf("[%d,%d]\t",i,j);
For(i*m+j) printf("{(%d,%d),%d,%d} ",V/m,V%m,E[h].cap,E[h].flow);
puts("");
}
}
int main(){
//freopen("1.txt","r",stdin);
init();
//debug();
while (bfs()) //分层操作
ans+=find(S,1000000000); //找出若干增广路径时增加的流最大
printf("%d\n",ans);
}
rápido
Más tarde, vi que parecía tener algo que ver con la "imagen dual", así que fui a aprender ...