费用流模板(带权二分图匹配)——hdu1533

/*
带权二分图匹配
用费用流求,增加源点s 和 汇点t
*/
#include<bits/stdc++.h>
using namespace std;
#define maxn 10005
#define maxm 200005
struct Edge{int to,nxt,w,c;}e[maxm<<1];
int head[maxn],tot,n,m,s,t,ans,maxflow;
char mp[maxn][maxn];
vector<pair<int,int> >M,H;
void add(int u,int v,int w,int c){
    e[tot].to=v;e[tot].w=w;e[tot].c=c;e[tot].nxt=head[u];head[u]=tot++;
    e[tot].to=u;e[tot].w=0;e[tot].c=-c;e[tot].nxt=head[v];head[v]=tot++;
}

int d[maxn],v[maxn],incf[maxn],pre[maxn];
bool spfa(){
    queue<int>q;
    memset(d,0x3f,sizeof d);
    memset(v,0,sizeof v);
    q.push(s);d[s]=0;v[s]=1;
    incf[s]=1<<30;
    while(q.size()){
        int x=q.front();q.pop();v[x]=0;
        for(int i=head[x];i!=-1;i=e[i].nxt){
            int y=e[i].to;
            if(e[i].w==0)continue;
            if(d[y]>d[x]+e[i].c){
                d[y]=d[x]+e[i].c;
                incf[y]=min(incf[x],e[i].w);
                pre[y]=i;
                if(!v[y])v[y]=1,q.push(y);
            }
        }
    }
    if(d[t]==0x3f3f3f3f)return false;
    return true;
}
void update(){
    int x=t;
    while(x!=s){
        int i=pre[x];
        e[i].w-=incf[t];
        e[i^1].w+=incf[t];
        x=e[i^1].to;
    }
    maxflow+=incf[t];
    ans+=d[t]*incf[t];
}

void init(){
    memset(head,-1,sizeof head);
    tot=ans=maxflow=0;
    M.clear();H.clear();
}
int dis(pair<int,int> a,pair<int,int> b){
    return abs(a.first-b.first)+abs(a.second-b.second);
}

int main(){
    while(cin>>n>>m&&n){
        init();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                scanf("\n%c",&mp[i][j]);
                if(mp[i][j]==‘m‘)
                    M.push_back(make_pair(i,j));
                if(mp[i][j]==‘H‘)
                    H.push_back(make_pair(i,j));
            }
        s=0,t=2*M.size()+1;
        for(int i=0;i<M.size();i++)
            add(s,i+1,1,0);
        for(int i=0;i<H.size();i++)
            add(i+1+M.size(),t,1,0);
        for(int i=0;i<M.size();i++)
            for(int j=0;j<H.size();j++)
                add(i+1,j+1+M.size(),1,dis(M[i],H[j]));
        while(spfa())
            update();
        cout<<ans<<‘\n‘;
    }
}

原文地址:https://www.cnblogs.com/zsben991126/p/10995890.html

时间: 2024-10-06 11:20:38

费用流模板(带权二分图匹配)——hdu1533的相关文章

hdu5045:带权二分图匹配

题目大意 : n个人 做m道题,其中 每连续的n道必须由不同的人做 已知第i人做出第j题的概率为pij,求最大期望 思路:考虑每连续的n道题 都要n个人来做,显然想到了带权的二分图匹配 然后就是套模板了 代码: #include <iostream> #include <stdio.h> #include<string.h> #include<algorithm> #include<string> #include<ctype.h>

Glorious Brilliance (最短路 + 带权二分图匹配)

这是一道代码大题.一开始读错题意了,然后理解成直接看上去的那种相邻,然后想不通好久!!! 把不同联通的图分离出来,然后先预处理一下形成之后的相邻图的状态,然后根据01确定哪一些是需要更换状态的,然后建图,利用二分图KM算法去匹配最优方案.然后求出每一组更换的,利用原先已经求好的路径去储存答案. #include<bits/stdc++.h> using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 5e2 + 7; ve

KM(Kuhn-Munkres)算法求带权二分图的最佳匹配

KM(Kuhn-Munkres)算法求带权二分图的最佳匹配 相关概念 这个算法个人觉得一开始时有点难以理解它的一些概念,特别是新定义出来的,因为不知道是干嘛用的.但是,在了解了算法的执行过程和原理后,这些概念的意义和背后的作用就渐渐的显示出来了.因此,先暂时把相关概念列出来,看看,有个大概印象就好,等到了解了算法的流程后,在看原理中会有这些概念,那个时候回来细看就好了. 完备匹配:定义 设G=<V1,V2,E>为二部图,|V1|≤|V2|,M为G中一个最大匹配,且|M|=|V1|,则称M为V1

带权二分图的最大权匹配 KM算法模版

带权二分图的最大权匹配 KM算法模版 下面是kuangbin大神的模版,已通过西电oj1048的测试 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #include<stack> #include<queue> #include<set

二分图与网络流 带权二分图的最大匹配

二分图与网络流  带权二分图的最大匹配 在某书上偶然发现,二分图和网络流是有联系的,在子图u中建立超级源点,在子图v中建立超级汇点,源点到u和汇点到v的每条边容量设为1,u和v中的边的容量也设为1,求出最大流也就是原二分图的最大匹配了. 而求带权二分图的最大匹配也就很容易了,将u和v的权值设为容量,仍然建立超级源点和超级汇点转为网络流解决即可. 真是一切皆可网络流啊...

图论模板——最大流及费用流模板

图论模板--最大流及费用流模板 最大流--SAP 时间复杂度:O(v^2*e) const int MAXN=1010;//点数的最大值 const int MAXM=1010;//边数的最大值 const int INF=0x3f3f3f3f; struct Node { int from,to,next; int cap; }edge[MAXM]; int tol; int head[MAXN]; int dep[MAXN]; int gap[MAXN];//gap[x]=y :说明残留网络

KM算法【带权二分图完美匹配】

先orz litble--KM算法 为什么要用KM算法 因为有的题丧心病狂卡费用流 KM算法相比于费用流来说,具有更高的效率. 算法流程 我们给每一个点设一个期望值[可行顶标] 对于左边的点来说,就是期望能匹配到多大权值的右边的点 对于右边的点来说,就是期望能在左边的点的期望之上还能产生多少贡献 两个点能匹配,当且仅当它们的期望值之和为这条边的权值 一开始初始化所有左点的期望是其出边的最大值,因为最理想情况下当然是每个点都匹配自己能匹配最大的那个 右点期望为0 然后我们逐个匹配,当一个点匹配失败

洛谷P3381——费用流模板题

嗯..随便刷了一道费用流的模板题....来练练手. #include<iostream> #include<cstdio> #include<cstring> using namespace std; int h[5210],d[5210],used[5210],que[100010],last[5210]; int k=1,INF=0x7fffffff,ans1=0,ans2=0; inline int read(){ int t=1,num=0; char c=ge

并查集模板 &amp;&amp; 带权并查集模板

不带权: 1 int f[50050]; 2 void init(void) 3 { 4 for(int i=1;i<=n;i++) 5 f[i]=i; 6 } 7 int fd(int x) 8 { 9 return f[x]==x?x:fd[x]=fd(f[x]); 10 } 11 int uion(int x,int y) 12 { 13 int fa=fd(x),fb=fd(y); 14 if(fa!=fb)f[fa]=fb; 15 } 带权: 1 int f[K],rl[K]; 2 3