开始就想着要拆点,i与i‘连边容量为2,费用为矩阵中的值,但是一想就不对了,如果这样的话,每个点可以走两次,每次的费用都是一样的,应该有一次为0才对,所以应该加两条边,容量都是1,一条边的费用为0。然后往左,下连边,,,跑费用流,求出最大的费用。。。
hdu 3376 数据开大些就可以了,N=720010
#include<stdio.h> #include<string.h> #include<queue> const int N=2000; const int inf=0x3fffffff; using namespace std; int dist[N],head[N],num,start,end,n,vis[N],pre[N]; struct edge { int st,ed,cost,flow,next; }e[N*10]; void addedge(int x,int y,int c,int w) { e[num].st=x;e[num].ed=y;e[num].cost=c; e[num].flow=w;e[num].next=head[x];head[x]=num++; e[num].st=y;e[num].ed=x;e[num].cost=-c;e[num].flow=0;e[num].next=head[y];head[y]=num++; } int SPFA() { queue<int>Q; int i,v,u; for(i=0;i<=end;i++) {dist[i]=-1;vis[i]=0;pre[i]=-1;} dist[start]=0;vis[start]=1; Q.push(start); while(!Q.empty()) { u=Q.front();Q.pop(); vis[u]=0; for(i=head[u];i!=-1;i=e[i].next) { v=e[i].ed; if(e[i].flow>0&&dist[v]<dist[u]+e[i].cost) { dist[v]=dist[u]+e[i].cost; pre[v]=i; if(vis[v]==0) { Q.push(v); vis[v]=1; } } } } if(pre[end]==-1) return 0; return 1; } int Maxcost() { int i,maxflow=0,minflow,maxcost=0; while(SPFA()) { minflow=inf; for(i=pre[end];i!=-1;i=pre[e[i].st]) if(minflow>e[i].flow) minflow=e[i].flow; maxflow+=minflow; for(i=pre[end];i!=-1;i=pre[e[i].st]) { e[i].flow-=minflow; e[i^1].flow+=minflow; maxcost+=e[i].cost; } } //printf("maxflow=%d\n",maxflow); return maxcost; } int main() { int i,j,t,x,w; while(scanf("%d",&n)!=-1) { t=n*n;start=0;end=t*2+1;num=0; memset(head,-1,sizeof(head)); addedge(start,1,0,2); addedge(t+t,end,0,2); for(i=1;i<=n;i++) for(j=1;j<=n;j++) { scanf("%d",&w); x=i*n+j-n; addedge(x,x+t,w,1); addedge(x,x+t,0,1); if(j+1<=n) addedge(x+t,x+1,0,2); if(i+1<=n) addedge(x+t,x+n,0,2); } printf("%d\n",Maxcost()); } return 0; }
’