zoukankan      html  css  js  c++  java
  • Going Home HDU

    http://acm.hdu.edu.cn/showproblem.php?pid=1533

    给一个网格图,每两个点之间的匹配花费为其曼哈顿距离,问给每个的"$m$"匹配到一个"$H$"的最小花费

    思路:

    实际上应该是一道KM匹配的题,不过也可以转化为费用流

    建立附加源汇点,$m$连接源点,$H$连接汇点,其余建立$num(H)*num(m)$条边,容量为1,费用为曼哈顿距离,跑一边费用流就行....

    #include <bits/stdc++.h>
    #define ll long long
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define pp pair<int,int>
    #define rep(ii,a,b) for(int ii=a;ii<=b;ii++)
    #define	per(ii,a,b) for(int ii=a;ii>=b;ii--)
    #define show(x) cout<<#x<<"="<<x<<endl
    #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl
    #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
    #define showa(a,b) cout<<#a<<'['<<b<<"]="<<b[a]<<endl
    using namespace std;
    const int maxn=1e5+10;
    const int maxm=1e6+10;
    const int INF=0x3f3f3f3f;
    int casn,n,m,k;
    struct node {
    	int pre,to,cap,cost,next;
    }e[maxm];
    int head[maxn],nume,inq[maxn],sum,ans;
    int q[maxn],pre[maxn],dis[maxn];
    int num[maxn],ss,tt;
    inline void addx(int a,int b,int c,int d){
    	e[++nume]={a,b,c,d,head[a]};
    	head[a]=nume;
    }
    inline void add(int a,int b,int c,int d){
    	addx(a,b,c,d);addx(b,a,0,-d);
    }
    bool spfa(int s=ss,int t=tt){
    	for(int i=0;i<=t;i++)dis[i]=INF;
    	dis[s]=q[0]=s;
    	int top=0,end=1;
    	while(top!=end){
    		int now=q[top++];top%=maxn;
    		for(int i=head[now];i;i=e[i].next){
          int to=e[i].to;
    			if(e[i].cap&&dis[to]>dis[now]+e[i].cost){
    				pre[to]=i;
    				dis[to]=dis[now]+e[i].cost;
    				if(!inq[to]){
    					inq[e[i].to]=true;
              if(dis[to]<dis[q[top]]){
                top=(top==0)?maxn-1:top-1;
    		  		  q[top]=to;
    					}else{
    						q[end++]=to;end%=maxn;
    					}
    				}
    			}
    		}
    		inq[now]=false;
    	}
    	return dis[t]!=INF;
    }
    
    void dfs(int s=ss,int t=tt){
    	int flow=INF;
    	for(int i=pre[t];i;i=pre[e[i].pre]) flow=min(flow,e[i].cap);
    	for(int i=pre[t];i;i=pre[e[i].pre]) {
    		e[i].cap-=flow;
    		e[i^1].cap+=flow;
    		ans+=e[i].cost*flow;
    	}
    }
    int hh[123][2];
    int mm[123][2];
    int main(){
    //#define test
    #ifdef test
    	freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
    #endif
    	IO;
      while(cin>>n>>m,n+m){
        nume=1;
        int cnt1=0,cnt2=0;
        char ch;
        memset(head,0,sizeof head);
        nume=1;
        for(int i=1;i<=n;i++){
          for(int j=1;j<=m;j++){
            cin>>ch;
            if(ch=='m') {
              mm[++cnt1][0]=i;
              mm[cnt1][1]=j;
            }
            if(ch=='H') {
              hh[++cnt2][0]=i;
              hh[cnt2][1]=j;
            }
          }
        }
        ss=0,tt=cnt1+cnt2+1;
        for(int i=1;i<=cnt1;i++){
          add(ss,i,1,0);
          for(int j=1;j<=cnt2;j++){
            add(i,j+cnt1,1,abs(hh[j][0]-mm[i][0])+abs(hh[j][1]-mm[i][1]));
          }
        }
        for(int i=1;i<=cnt2;i++){
          add(i+cnt1,tt,1,0);
        }
        ans=0;
        while(spfa())dfs();
        cout<<ans<<endl;
      }
    #ifdef test
    	fclose(stdin);fclose(stdout);system("out.txt");
    #endif
    	return 0;
    }
    

      

  • 相关阅读:
    前端基础之CSS
    前端基础之HTML(三)
    前端基础之HTML(二)
    前端基础之HTML(一)
    面向对象总结
    内置函数总结
    函数部分总结
    文件操作总结
    基础数据类型总结
    python基础知识总结
  • 原文地址:https://www.cnblogs.com/nervendnig/p/9095003.html
Copyright © 2011-2022 走看看