zoukankan      html  css  js  c++  java
  • POJ2195:Going Home(费用流入门)

    http://poj.org/problem?id=2195

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <queue>
    #include <math.h>
    #define inf 0x3f3f3f3f
    using namespace std;
    int n,m,s,t,tt;
    struct pointe
    {
        int x,y;
    } l[1001],r[1001];
    struct node
    {
        int x,y,c,w;
        int next;
    } eg[20001];
    char map[102][102];
    int head[1001],v[1001],dis[1001],pre[1001];
    void init()
    {
        memset(head,-1,sizeof(head));
        tt=0;
        s=0;
        t=n*m+1;
    }
    void add(int xx,int yy,int cc,int ww)
    {
        eg[tt].x=xx;
        eg[tt].y=yy;
        eg[tt].c=cc;
        eg[tt].w=ww;
        eg[tt].next=head[xx];
        head[xx]=tt++;
        eg[tt].x=yy;
        eg[tt].y=xx;
        eg[tt].c=0;
        eg[tt].w=-ww;
        eg[tt].next=head[yy];
        head[yy]=tt++;
    }
    int spfa(int s,int t)
    {
        for(int i=s; i<=t; i++)
        {
            v[i]=0;
            pre[i]=-1;
            dis[i]=inf;
        }
        queue<int>q;
        dis[s]=0;
        q.push(s);
        while(!q.empty())
        {
            int ff=q.front();
            q.pop();
            v[ff]=0;
            //今天算是刚了解邻接边表第一次更新的是与源点相邻的第一层
            //例如head[10]->1,3,5,7....;
            for(int i=head[ff]; i!=-1; i=eg[i].next)
            {
                int w1=eg[i].y;
                if(eg[i].c&&dis[w1]>dis[ff]+eg[i].w)
                {
                    dis[w1]=dis[ff]+eg[i].w;//注意这里dis[ff]
                    pre[w1]=i;//算是了解么意思了
                    if(!v[w1])
                    {
                        v[w1]=1;
                        q.push(w1);
                    }
                }
            }
        }
        if(dis[t]==inf)
        {
            return 0;
        }
        return 1;
    }
    void KM(int s,int t)
    {
        int ans=0,minx;
        while(spfa(s,t)==1)
        {
            minx=inf;
            for(int i=pre[t]; i!=-1; i=pre[eg[i].x])
                minx=min(minx,eg[i].c);
            for(int i=pre[t]; i!=-1; i=pre[eg[i].x])
            {
                eg[i].c-=minx;
                eg[i+1].c+=minx;
            }
            ans+=minx*dis[t];
        }
        cout<<ans<<endl;
        return ;
    }
    int main()
    {
        int t1,t2,temp;
        while(scanf("%d%d",&n,&m)!=EOF&&(n||m))
        {
            t1=t2=0;
            init();
            for(int i=1; i<=n; i++)
                scanf("%*c%s",map[i]+1);
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=m; j++)
                {
                    temp=(i-1)*m+j;
                    if(map[i][j]=='m')
                    {
                        add(s,temp,1,0);
                        l[t1].x=i;
                        l[t1++].y=j;
                    }
                    else if(map[i][j]=='H')
                    {
                        add(temp,t,1,0);
                        r[t2].x=i;
                        r[t2++].y=j;
                    }
                }
            }
            for(int i=0; i<t1; i++)
            {
                int l1=(l[i].x-1)*m+l[i].y;
                for(int j=0; j<t2; j++)
                {
                    int l2=(r[j].x-1)*m+r[j].y;
                    int l3=abs(l[i].x-r[j].x)+abs(l[i].y-r[j].y);
                    add(l1,l2,1,l3);
                }
            }
            KM(s,t);
        }
        return 0;
    }
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <queue>
    #include <math.h>
    #define inf 0x3f3f3f3f
    using namespace std;
    struct node1//记录h或者m的坐标
    {
        int x,y;
    } a[402],b[402];
    struct node
    {
        int x,y,c,w;
        int next;
    } eg[600001];
    int n,m,tt,head[10001],v[10001],dis[10001],pre[10001],s,t;
    char map[102][102];
    void init()
    {
        tt=0;
        memset(head,-1,sizeof(head));
        s=0;
        t=n*m+1;
    }
    void add(int xx,int yy,int cc,int ww)
    {
        eg[tt].x=xx;
        eg[tt].y=yy;
        eg[tt].c=cc;
        eg[tt].w=ww;
        eg[tt].next=head[xx];
        head[xx]=tt++;
        eg[tt].x=yy;
        eg[tt].y=xx;
        eg[tt].c=0;
        eg[tt].w=-ww;
        eg[tt].next=head[yy];
        head[yy]=tt++;
    }
    int spfa(int s,int t)
    {
        queue<int>q;
        for(int i=0; i<=t; i++)
        {
            v[i]=0;
            dis[i]=inf;
            pre[i]=-1;
        }
        v[s]=1;
        dis[s]=0;
        q.push(s);
        while(!q.empty())
        {
            int ff=q.front();
            q.pop();
            v[ff]=0;
            for(int i=head[ff]; i!=-1; i=eg[i].next)
            {
                int w1=eg[i].y;
                if(eg[i].c&&dis[w1]>dis[ff]+eg[i].w)
                {
                    dis[w1]=dis[ff]+eg[i].w;
                    pre[w1]=i;//用边表建图存储其信息
                    if(!v[w1])
                    {
                        v[w1]=1;
                        q.push(w1);
                    }
                }
            }
        }
        if(dis[t]==inf)
        {
            return 0;
        }
        return 1;
    }
    void KM(int s,int t)
    {
        int min1,ans=0;
        while(spfa(s,t)==1)
        {
            min1=inf;
            for(int i=pre[t]; i!=-1; i=pre[eg[i].x])
            {
                if(min1>=eg[i].c)
                {
                    min1=eg[i].c;
                }
            }
            for(int i=pre[t]; i!=-1; i=pre[eg[i].x])
            {
                eg[i].c-=min1;
                eg[i+1].c+=min1;
            }
            ans+=min1*dis[t];
        }
        printf("%d
    ",ans);
        return ;
    }
    int main()
    {
        int t1,t2;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            if(n==0&&m==0) break;
            init();
            t1=0;
            t2=0;
            for(int i=1; i<=n; i++)
            {
                scanf("%s",map[i]+1);//因为要创建超级源点,所以从一比较好计算
                for(int j=1; j<=m; j++)
                {
                    int l=(i-1)*m+j;//以点建图
                    if(map[i][j]=='m')
                    {
                        add(s,l,1,0);
                        a[t1].x=i;
                        a[t1++].y=j;
                    }
                    else if(map[i][j]=='H')
                    {
                        add(l,t,1,0);
                        b[t2].x=i;
                        b[t2++].y=j;
                    }
                }
            }
            for(int i=0; i<t1; i++)
            {
                int l1=(a[i].x-1)*m+a[i].y;//以点建图
                for(int j=0; j<t2; j++)
                {
                    int l2=abs(a[i].x-b[j].x)+abs(a[i].y-b[j].y);
                    int l3=(b[j].x-1)*m+b[j].y;//以点建图
                    add(l1,l3,1,l2);
                }
            }
            KM(s,t);
        }
        return 0;
    }
  • 相关阅读:
    IronRuby:元编程特性【method_missing】的使用
    DNN(DotNetNuke) 3.0感官刺激零距x接触!!! :)
    (MS SQL)如何实现相关文章功能(多关键字匹配)改进版
    谁有微软认证,如MCSD,MCDBA,MCXX等等,马上告诉我
    开源代码2004/12/25 codeproject
    开源代码2004/1220-PDF格式/文件相关
    强烈推荐一个超酷的跨平台、支持多数据库的数据库管理工具
    (MS SQL)如何实现相关文章功能(多关键字匹配)
    DotNetNuke(DNN)从入门到进阶(1)-怎样写自己的模块
    推荐开源代码2004/12/17
  • 原文地址:https://www.cnblogs.com/zhangmingcheng/p/4010677.html
Copyright © 2011-2022 走看看