zoukankan      html  css  js  c++  java
  • HDU 1533 Going Home (最小费用流)

    题意:

      一个矩阵n*m,其中有k个房子和k个人,k个人分别必须走到任意一个房子中(匹配),但是权值就是长度(非欧拉距离),求匹配完的权之和。

    思路:

      建图方法是,首先将k个人和k个房子分别抽出来到集合X和Y中,计算两两之间的距离,X到Y有一条边,费用为正,容量为1;Y到X也有一条边,费用为负,容量为0(其实两条边就是相反的)。添加一个源点0号到X集,添加一个汇点2*k+1号到Y集,这些费用都是0,容量都是1。

      建完图就用正常的方法(EK+SPFA)来解决就行了。由于我想要让每次增广路只找到流为1的路径,所以我在2*k+1号点后面还加个点2*k+2,仅1条边,费用为0,容量为1。这样每次spfa至多也只有1流量通过到汇点了。(可不用此法,将每次spfa所得cost[end]*flow[end]就行了,因为可能流过的并不止1流量。)

      

      1 #include <bits/stdc++.h>
      2 #define LL long long
      3 #define pii pair<int,int>
      4 #define INF 0x7f7f7f7f
      5 using namespace std;
      6 const int N=10000+20;
      7 vector<int> vect[N];
      8 int flow[N], cost[N], path[N], inq[N], edge_cnt;
      9 struct node
     10 {
     11     int from;
     12     int to;
     13     int val;
     14     int cap;
     15     int flo;
     16 }edge[N*4];//边数要自己估计,不然就会RE
     17 
     18 
     19 void add_node(int from,int to, int val, int cap, int flo)
     20 {
     21     edge[edge_cnt].from=from;
     22     edge[edge_cnt].to=to;
     23     edge[edge_cnt].val=val;
     24     edge[edge_cnt].cap=cap;
     25     edge[edge_cnt].flo=flo;
     26     vect[from].push_back(edge_cnt++);
     27 }
     28 
     29 int spfa(int s,int e)
     30 {
     31     deque<int> que;
     32     que.push_back(s);
     33     inq[s]=1;
     34     flow[s]=INF;
     35     cost[s]=0;
     36 
     37     while(!que.empty())
     38     {
     39         int x=que.front();
     40         que.pop_front();
     41         inq[x]=0;
     42         for(int i=0; i<vect[x].size(); i++)
     43         {
     44             node e=edge[vect[x][i]];
     45             if(e.cap>e.flo && cost[e.to]>cost[e.from] + e.val)
     46             {
     47                 cost[e.to]=cost[x]+ e.val;//每次的流最多只是1。
     48                 path[e.to]=vect[x][i];
     49                 flow[e.to]=min(flow[e.from], e.cap-e.flo);
     50                 if(!inq[e.to])
     51                 {
     52                     inq[e.to]=1;
     53                     que.push_back(e.to);
     54                 }
     55             }
     56         }
     57     }
     58     return cost[e];
     59 }
     60 
     61 int cal(int s,int e)
     62 {
     63     int ans=0;
     64     while(true)
     65     {
     66         memset(flow, 0, sizeof(flow));
     67         memset(cost, 0x7f, sizeof(cost));
     68         memset(path, 0, sizeof(path));
     69         memset(inq, 0, sizeof(inq));
     70 
     71         if(spfa(s,e)==INF) return ans;
     72         ans+=cost[e]; 
     73 
     74         int ed=e-1;//连e点那条边不清空,可以保证每次至多1流。
     75         while(ed!=s)
     76         {
     77             int t=path[ed];
     78             edge[t].flo++;
     79             edge[t^1].flo--;
     80             ed=edge[t].from;
     81         }
     82     }
     83 }
     84 
     85 int main()
     86 {
     87     freopen("input.txt", "r", stdin);
     88     int n, m;char ch;
     89     while(~scanf("%d%d",&n,&m),n+m)
     90     {
     91         for(int i=N-1; i>=0; i--)    vect[i].clear();
     92         memset(edge, 0, sizeof(edge));
     93         edge_cnt=0;
     94         int cnt=0;
     95         vector<pii> vect_h,vect_m;
     96 
     97         for(int i=1; i<=n; i++)
     98             for(int j=1; j<=m; j++)
     99             {
    100                 cin>>ch;
    101                 if(ch=='H')    vect_h.push_back(make_pair(i,j)),cnt++;
    102                 if(ch=='m')    vect_m.push_back(make_pair(i,j));
    103             }
    104 
    105 
    106         for(int i=0; i<vect_m.size(); i++)
    107         {
    108             int a=vect_m[i].first, b=vect_m[i].second;
    109             for(int j=0; j<vect_h.size(); j++)
    110             {
    111                 int c=vect_h[j].first, d=vect_h[j].second;
    112                 int dis=abs(c-a)+abs(d-b);
    113 
    114                 add_node(i+1,cnt+j+1,dis,1,0);
    115                 add_node(cnt+j+1,i+1,-dis,0,0);
    116             }
    117         }
    118 
    119         for(int i=0; i<vect_m.size(); i++)            //添加源点
    120         {
    121             add_node(0,i+1,0,1,0);
    122             add_node(i+1,0,0,0,0);
    123 
    124         }
    125         for(int j=0; j<vect_h.size(); j++)          //添加汇点
    126         {
    127             add_node(cnt+j+1,cnt*2+1,0,1,0);
    128             add_node(cnt*2+1,cnt+j+1,0,0,0);
    129         }
    130         add_node(cnt*2+1,cnt*2+2, 0, 1, 0);     //这是为了每次只流过1。再汇点后面再加个汇点,容量是1,但是每次spfa后都不增加flow。
    131         add_node(cnt*2+2,cnt*2+1, 0, 0, 0);
    132         cout<<cal(0,cnt*2+2)<<endl;
    133     }
    134     return 0;
    135 }
    AC代码
  • 相关阅读:
    base64是什么东东,base64 图片显示,在线编辑器
    中文字符 与 十六进制Unicode编码 相互转换
    全面理解Python中self的用法
    Python之使用元类MetaClass
    Python之MySQL数据库连接驱动aiomysql的使用
    Python实战网站开发:Day2编写Web App骨架
    Python实战网站开发:Day3编写ORM
    Python之MySQL数据库连接驱动pymysql的使用
    【CV基础】为什么一些深度学习的图像预处理使用mean=[0.485, 0.456, 0.406] and std=[0.229, 0.224, 0.225]来正则化?
    与人合作创业是一门大艺术(转)
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4644005.html
Copyright © 2011-2022 走看看