hdu4862(14多校第一场B题)及最小费用最大流模板

来源:互联网 发布:matlab的优化工具箱 编辑:程序博客网 时间:2024/05/01 23:34

解题思路:

建立一个流量网络,一个二部图。X部分向Y部分链接的情况表示可以从一个点跳到另一个点,超级源点和超级汇点分别同X部分的点和Y部分的点链接。在X部分中多加一个点它与源点的流量是K费用是0,与Y部分所有点链接流量是1费用是0。这表示操作K次。

#include<iostream>#include<cstdio>#include<cstring>#include<queue>#define rep(i,a,b)for (int i=a;i<(b+1);i++)using namespace std;const int maxn=250;const int inf=1<<29;const int maxm=maxn*maxn*5;int n,m,k,st,end,head[maxn]={0},pnt[maxm],cnt,nxt[maxm],cost[maxm],flow[maxm],pre[maxn],dis[maxn];char s[maxn][maxn];void addedge(int u,int v,int c,int f){pnt[cnt]=v;nxt[cnt]=head[u];cost[cnt]=c;flow[cnt]=f;head[u]=cnt++;pnt[cnt]=u;nxt[cnt]=head[v];cost[cnt]=-c;flow[cnt]=0;head[v]=cnt++;}bool spfa(){bool vis[maxn]={false};rep(i,st,end+1){pre[i]=-1;dis[i]=inf;}dis[st]=0;queue<int> q;vis[st]=true;q.push(st);while (!q.empty()){int u=q.front();q.pop();for (int i=head[u];i!=-1;i=nxt[i])if (flow[i]&&dis[u]+cost[i]<dis[pnt[i]]){dis[pnt[i]]=dis[u]+cost[i];pre[pnt[i]]=i;if (!vis[pnt[i]]){q.push(pnt[i]);vis[pnt[i]]=true;}}vis[u]=false;}return dis[end]!=inf;}void Build(){cnt=0;memset(pnt,0,sizeof pnt);memset(nxt,0,sizeof nxt);memset(cost,0,sizeof cost);memset(flow,0,sizeof flow);st=0,end=2*n*m+1;int p=2*n*m+2;memset(head,-1,sizeof head);addedge(st,p,0,k);rep(i,1,n*m){addedge(st,i,0,1);addedge(n*m+i,end,0,1);addedge(p,n*m+i,0,1);}rep(i,0,n-1)rep(j,0,m-1){rep(k,j+1,m-1)if (s[i][j]==s[i][k])addedge(i*m+j+1,n*m+i*m+k+1,-(s[i][j]-'0'-(k-j-1)),1);else addedge(i*m+j+1,n*m+i*m+k+1,k-j-1,1);rep(k,i+1,n-1)if (s[i][j]==s[k][j])addedge(i*m+j+1,n*m+k*m+j+1,-(s[i][j]-'0'-(k-i-1)),1);else addedge(i*m+j+1,n*m+k*m+j+1,k-i-1,1);}}void mincostflow(){int ans=0,sum=0;while (spfa()){int mini=inf;for (int i=pre[end];i!=-1;i=pre[pnt[i^1]])mini=min(mini,flow[i]);for (int i=pre[end];i!=-1;i=pre[pnt[i^1]]){flow[i]-=mini;flow[i^1]+=mini;}sum+=mini;ans+=dis[end]*mini;}if (sum==n*m)printf("%d\n",-ans);else printf("-1\n");}int main(){int T;scanf("%d",&T);rep(z,1,T){scanf("%d%d%d",&n,&m,&k);rep(i,0,n-1)scanf("%s",s[i]);printf("Case %d : ",z);Build();mincostflow();}return 0;}


0 0