2 10 3 5 10 3 10 3 3 2 5 3 6 7 10 5 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8 5 6 7 8 9
28 46 80
#include<stdio.h> #include<string.h> #include<queue> using namespace std; const int MAXN = 10010; const int MAXM = 1001000; const int INF = 1<<30; struct EDG{ int to,next,cap,flow; int cost; //单价 }edg[MAXM]; int head[MAXN],eid; int pre[MAXN], cost[MAXN] ; //点0~(n-1) void init(){ eid=0; memset(head,-1,sizeof(head)); } void addEdg(int u,int v,int cap,int cst){ edg[eid].to=v; edg[eid].next=head[u]; edg[eid].cost = cst; edg[eid].cap=cap; edg[eid].flow=0; head[u]=eid++; edg[eid].to=u; edg[eid].next=head[v]; edg[eid].cost = -cst; edg[eid].cap=0; edg[eid].flow=0; head[v]=eid++; } bool inq[MAXN]; bool spfa(int sNode,int eNode , int n){ queue<int>q; for(int i=0; i<n; i++){ inq[i]=false; cost[i]= -1; } cost[sNode]=0; inq[sNode]=1; pre[sNode]=-1; q.push(sNode); while(!q.empty()){ int u=q.front(); q.pop(); inq[u]=0; for(int i=head[u]; i!=-1; i=edg[i].next){ int v=edg[i].to; if(edg[i].cap-edg[i].flow>0 && cost[v]<cost[u]+edg[i].cost){ //在满足可增流的情况下,最小花费 cost[v] = cost[u]+edg[i].cost; pre[v]=i; //记录路径上的边 if(!inq[v]) q.push(v),inq[v]=1; } } } return cost[eNode]!=-1; //判断有没有增广路 } //反回的是最大流,最小花费为minCost int minCost_maxFlow(int sNode,int eNode ,int& minCost , int n){ int ans=0; while(spfa(sNode,eNode , n)){ for(int i=pre[eNode]; i!=-1; i=pre[edg[i^1].to]){ edg[i].flow+=1; edg[i^1].flow-=1; minCost+=edg[i].cost; } ans++; if(ans==2)break; } return ans; } int main(){ int n,mapt[35][35]; while(scanf("%d",&n)>0){ init(); for(int i=0; i<n; i++) for(int j=0; j<n; j++) scanf("%d",&mapt[i][j]); int s = 0 , t = n*n-1; for(int i=0; i<n; i++) for(int j=0; j<n; j++) if(i||j){ addEdg(i*n+j , i*n+j+n*n , 1 , mapt[i][j]); if(j+1<n) addEdg(i*n+j+n*n, i*n+j+1 , 1 , 0 ); if(i+1<n) addEdg(i*n+j+n*n, (i+1)*n+j , 1 , 0); } else{ addEdg(s , 1 , 1,0) , addEdg(s , n , 1 , 0); } int maxCost=mapt[0][0]; if(n>1) maxCost+=mapt[n-1][n-1]; minCost_maxFlow(s , t , maxCost , n*n*2); printf("%d\n",maxCost); } }
原文地址:http://blog.csdn.net/u010372095/article/details/46641679