zoukankan      html  css  js  c++  java
  • hdu1533 最小费用最大流

    题意

    题意很简单,给一张100*100以内的图,H和m个数相同,进行匹配,求路径最小的一个方案

    思路

    建立两个源点,s和t。然后将H和m的位置离散化,s连接H,t连接s,H和m连接流量1,费用为两个坐标的曼哈顿距离。bellmanford一套就ok

    bellmanford模板

    struct node{
        int next,to,flow,cost,c;
    }edge[M];
    int head[N],tot,s,t;
    int maxflow,mincost;//最大流 最小费用
    void inint(){mem(head,-1);tot=0;}
    void add(int u,int v,int c,int cost){
        edge[tot].next=head[u];edge[tot].to=v;edge[tot].c=c;edge[tot].flow=0;edge[tot].cost=cost;head[u]=tot++;
        edge[tot].next=head[v];edge[tot].to=u;edge[tot].c=0;edge[tot].flow=0;edge[tot].cost=-cost;head[v]=tot++;
    }
    int dis[N],vis[N],pv[N],pe[N],a[N];
    bool bellmanford(int s,int t){
        for(int i=0;i<N;i++){dis[i]=inf;vis[i]=0;pv[i]=-1;}
        dis[s]=0;pv[s]=-1;a[s]=inf;
        queue<int>q;
        q.push(s);
        vis[s]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head[u];~i;i=edge[i].next){
                int v=edge[i].to,cap=edge[i].c,flow=edge[i].flow,cost=edge[i].cost;
                if(cap>flow && dis[v]>dis[u]+cost){
                    dis[v]=dis[u]+cost;
                    pv[v]=u;
                    pe[v]=i;
                    a[v]=min(a[u],cap-flow);
                    if(!vis[v]){
                        q.push(v);
                        vis[v]=1;
                    }
                }
            }
        }
        if(dis[t]==inf){
            return false;
        }
        maxflow+=a[t];
        mincost+=dis[t]*a[t];
        for(int i=t;i!=s;i=pv[i]){
            edge[pe[i]].flow+=a[t];
            edge[pe[i]^1].flow-=a[t];
        }
        return true;
    }
    void kkkk(){
        while(bellmanford(s,t)){continue;}
        return;
    }
    

    ac代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define il inline
    #define it register int
    #define inf 0x3f3f3f3f
    #define lowbit(x) (x)&(-x)
    #define pii pair<int,int>
    #define mak(a,b) make_pair(a,b)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mod 1000000007
    const double pi=acos(-1.0);
    const int N=1e4+10,M=2e5+10;
    int n,m;
    char mp[110][110];
    int H[10010],man[10010],Hnum,mannum;
    struct node{
        int next,to,flow,cost,c;
    }edge[M];
    int head[N],tot,s,t;
    int maxflow,mincost;//最大流 最小费用
    void inint(){mem(head,-1);tot=0;}
    void add(int u,int v,int c,int cost){
        edge[tot].next=head[u];edge[tot].to=v;edge[tot].c=c;edge[tot].flow=0;edge[tot].cost=cost;head[u]=tot++;
        edge[tot].next=head[v];edge[tot].to=u;edge[tot].c=0;edge[tot].flow=0;edge[tot].cost=-cost;head[v]=tot++;
    }
    int dis[N],vis[N],pv[N],pe[N],a[N];
    bool bellmanford(int s,int t){
        for(int i=0;i<N;i++){dis[i]=inf;vis[i]=0;pv[i]=-1;}
        dis[s]=0;pv[s]=-1;a[s]=inf;
        queue<int>q;
        q.push(s);
        vis[s]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head[u];~i;i=edge[i].next){
                int v=edge[i].to,cap=edge[i].c,flow=edge[i].flow,cost=edge[i].cost;
                if(cap>flow && dis[v]>dis[u]+cost){
                    dis[v]=dis[u]+cost;
                    pv[v]=u;
                    pe[v]=i;
                    a[v]=min(a[u],cap-flow);
                    if(!vis[v]){
                        q.push(v);
                        vis[v]=1;
                    }
                }
            }
        }
        if(dis[t]==inf){
            return false;
        }
        maxflow+=a[t];
        mincost+=dis[t]*a[t];
        for(int i=t;i!=s;i=pv[i]){
            edge[pe[i]].flow+=a[t];
            edge[pe[i]^1].flow-=a[t];
        }
        return true;
    }
    void kkkk(){
        while(bellmanford(s,t)){continue;}
        return;
    }
    int main(){
        while(~scanf("%d%d",&n,&m)){
            if(n==0&& m==0){return 0;}
            getchar();inint();
            for(int i=0;i<n;i++){
                scanf("%s",mp[i]);
            }
            Hnum=0;mannum=0;
            map<int,int>num;int cnt=1;
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                    if(mp[i][j]=='H'){
                        H[Hnum++]=i*100+j;
                    }
                    else if(mp[i][j]=='m'){
                        man[mannum++]=i*100+j;
                    }
                }
            }
            s=0;t=Hnum+mannum+1;maxflow=0;mincost=0;
            for(int i=0;i<Hnum;i++){
                for(int j=0;j<mannum;j++){
                    if(num[H[i]]==0){
                        num[H[i]]=cnt++;
                    }
                    if(num[man[j]]==0){
                        num[man[j]]=cnt++;
                    }
                    add(num[H[i]],num[man[j]],1,abs(H[i]/100-man[j]/100)+abs(H[i]%100-man[j]%100));
    
                }
            }
            for(int i=0;i<Hnum;i++)add(s,num[H[i]],1,0);
            for(int j=0;j<mannum;j++)add(num[man[j]],t,1,0);
            kkkk();
            //cout<<maxflow<<endl;
            printf("%d
    ",mincost);
        }
        return 0;
    }
    
  • 相关阅读:
    linux学习之路7 linux下获取帮助
    51nod 1002 数塔取数问题
    51nod 1002 数塔取数问题
    51nod 1001 数组中和等于K的数对
    51nod 1001 数组中和等于K的数对
    linux学习之路6 Vi文本编辑器
    linux学习之路6 Vi文本编辑器
    计算误差——ACM计算几何中的精度问题
    计算误差——ACM计算几何中的精度问题
    daily_journal_3 the game of thrones
  • 原文地址:https://www.cnblogs.com/luoyugongxi/p/13751329.html
Copyright © 2011-2022 走看看