zoukankan      html  css  js  c++  java
  • POJ 2195 Going Home | 带权二分图匹配

    给个地图有人和房子

    保证人==房子,每个人移动到房子处需要花费曼哈顿距离的代价

    问让人都住在房子里最小代价


    显然是个带权二分图最大匹配

    转化成以一个网络,规定w是容量,c是代价

    1.S向人连边,w=1,c=0

    2.房子向T连边,w=1,c=0

    3.人向房子连边 w=1,c=距离

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<vector>
    #define N 10000
    #define INF 1000000000
    using namespace std;
    deque <int> q;
    int head[N],lev[N],dist[N],n,m,ecnt=1,vis[N],S,T,ans,H,M;
    char mp[110][110];
    struct adj
    {
        int nxt,v,w,c;
    }e[200*200];
    int Abs(int x)
    {return x>0?x:-x;}
    struct coor
    {
        int x,y;
        int operator - (const coor &a)const
    	{return Abs(x-a.x)+Abs(y-a.y);}
    };
    coor make(int x,int y)
    {
        coor ret;
        ret.x=x,ret.y=y;
        return ret;
    }
    vector <coor> house,man;
    inline void add(int u,int v,int w,int c)
    {
        e[++ecnt].v=v,e[ecnt].w=w,e[ecnt].c=c,e[ecnt].nxt=head[u],head[u]=ecnt;
        e[++ecnt].v=u,e[ecnt].w=0,e[ecnt].c=-c,e[ecnt].nxt=head[v],head[v]=ecnt;
    }
    inline int spfa(int s,int t)
    {
        int v;
        memset(vis,0,sizeof(vis));
        for (int i=s;i<=t;i++) dist[i]=INF;
        dist[t]=0,vis[t]=1;
        q.push_back(t);
        while (!q.empty())
        {
        int u=q.front();q.pop_front();
        for (int i=head[u];i;i=e[i].nxt)
            if (e[i^1].w>0 && dist[v=e[i].v]>dist[u]-e[i].c)
            {
            dist[v]=dist[u]-e[i].c;
            if (!vis[v])
            {
                vis[v]=1;
                if (!q.empty() && dist[v]<dist[q.front()])
                q.push_front(v);
                else
                q.push_back(v);
            }
            }
        vis[u]=0;
        }
        return dist[s]<INF;
    }
    inline int dfs(int x,int flow)
    {
        if (x==T)
        return vis[T]=1,flow;
        int used=0,tmp,v;
        vis[x]=1;
        for (int i=head[x];i;i=e[i].nxt)
        if (!vis[v=e[i].v] && e[i].w>0 && dist[x]-e[i].c==dist[v])
        {
            tmp=dfs(v,min(e[i].w,flow-used));
            if (tmp>0)
            ans+=tmp*e[i].c,e[i].w-=tmp,e[i^1].w+=tmp,used+=tmp;
            if (used==flow) break;
        }
        return used;
    }
    inline int CostFlow()
    {
        int Flow=0;
        while (spfa(S,T))
        {
    	vis[T]=1;
    	while (vis[T])
    	{
    	    memset(vis,0,sizeof(vis));
    	    Flow+=dfs(S,INF);
    	}
        }
        return Flow;
    }
    void init()
    {
        memset(head,0,sizeof(head));
        man.clear();
        house.clear();
        ans=M=H=0;
        ecnt=1;
    }
    int main()
    {
        while (scanf("%d%d",&n,&m)!=EOF)
        {
    	if (n==0 && m==0) break;
    	init();
    	for (int i=1;i<=n;i++)
    	    scanf("%s",mp[i]+1);
    	for (int i=1;i<=n;i++)
    	    for (int j=1;j<=m;j++)
    		if (mp[i][j]=='m')
    		    man.push_back(make(i,j)),M++;
    		else if (mp[i][j]=='H')
    		    house.push_back(make(i,j)),H++;
    	T=H+M+1;
    	for (int i=0;i<M;i++)
    	    for (int j=0;j<H;j++)
    		add(i+1,M+j+1,1,man[i]-house[j]);
    	for (int i=1;i<=M;i++)
    	    add(S,i,1,0);
    	for (int i=1;i<=H;i++)
    	    add(M+i,T,1,0);
           CostFlow();
    	printf("%d
    ",ans);
        }
    	
        return 0;
    }
    
  • 相关阅读:
    编写可测试的程序
    系统程序员成长计划序
    编写可移植C/C++程序的要点
    Android IPC机制详解
    WordPress Attack Scanner插件多个信息泄露漏洞
    WordPress Simple History Plugin RSS Feed 信息泄露漏洞
    WordPress Poll插件多个SQL注入漏洞
    WordPress yolink Search插件‘s’参数跨站脚本漏洞
    WordPress Poll插件跨站请求伪造漏洞
    Python 'stringobject.c'多个远程缓冲区溢出漏洞
  • 原文地址:https://www.cnblogs.com/mrsheep/p/7954010.html
Copyright © 2011-2022 走看看