bzoj3171 循环格 最小费用流

       虽然一眼看出是网络流,但是一直想不出正解。。想了好久。

       实际上,将方向看成一条有向边,每个点能回到自己不就是要求原图是若干个强联通分量吗?于是由于每个点出度为1,因此入读也只能为1,然后搞一个二分图,左边表示出去的点,右边表示到的点,然后对于可以走到一对点,连边容量为1,费用为1(需要修改)或0(不需要修改)。跑完美匹配的最小权值,转化成最小费用最大流即可。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#define inf 1000000000
#define N 4005
using namespace std;

int n,m,tot=1,fst[N],pnt[N],len[N],cst[N],nxt[N];
int h[N],ps[25][25],sta,gol,d[N],fa[N],e[N],ans=0;
bool bo[N]; char ch[N];
const int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
int exchg(char c){
	if (c=='U') return 0; if (c=='D') return 1;
	if (c=='L') return 2; return 3;
}
void add(int aa,int bb,int cc,int dd){
	pnt[++tot]=bb; len[tot]=cc; cst[tot]=dd; nxt[tot]=fst[aa]; fst[aa]=tot;
}
bool spfa(){
	int head=0,tail=1,i; h[1]=sta;
	for (i=0; i<=gol; i++) d[i]=inf; d[sta]=0;
	memset(bo,1,sizeof(bo));
	while (head!=tail){
		head=head%4000+1; int x=h[head],p; bo[x]=1;
		for (p=fst[x]; p; p=nxt[p]) if (len[p]){
			int y=pnt[p];
			if (d[x]+cst[p]<d[y]){
				d[y]=d[x]+cst[p]; fa[y]=x; e[y]=p;
				if (bo[y]){
					bo[y]=0; tail=tail%4000+1; h[tail]=y;
				}
			}
		}
	}
	return d[gol]<inf;
}
void updata(){
	int i,p,tmp=inf;
	for (i=gol; i!=sta; i=fa[i]){
		p=e[i]; tmp=min(tmp,len[p]);
	}
	for (i=gol; i!=sta; i=fa[i]){
		p=e[i];
		ans+=tmp*cst[p]; len[p]-=tmp; len[p^1]+=tmp;
	}
}
int main(){
	scanf("%d%d",&m,&n); int i,j,k,tmp=0;
	for (i=1; i<=m; i++)
		for (j=1; j<=n; j++) ps[i][j]=++tmp;
	for (i=1; i<=m; i++){
		scanf("%s",ch+1);
		for (j=1; j<=n; j++){
			int t=exchg(ch[j]);
			for (k=0; k<4; k++){
				int x=i+dx[k],y=j+dy[k];
				if (!x) x=m; if (x>m) x=1;
				if (!y) y=n; if (y>n) y=1;
				if (k==t){ add(ps[i][j],ps[x][y]+m*n,1,0); add(ps[x][y]+m*n,ps[i][j],0,0); }
					else{ add(ps[i][j],ps[x][y]+m*n,1,1); add(ps[x][y]+m*n,ps[i][j],0,-1); }
			}
		}
	}
	sta=0; gol=2*m*n+1;
	for (i=1; i<=m; i++)
		for (j=1; j<=n; j++){
			add(sta,ps[i][j],1,0); add(ps[i][j],sta,0,0);
			add(ps[i][j]+m*n,gol,1,0); add(gol,ps[i][j]+m*n,0,0);
		}
	while (spfa()) updata(); printf("%d\n",ans);
	return 0;
}

by lych
2016.2.18

你可能感兴趣的:(网络流,费用流,二分图,最小费用最大流)