zoukankan      html  css  js  c++  java
  • poj2195 bfs+最小权匹配

         题意:给个矩阵,矩阵里有一些人和房子(人数和房子数相等),一个人只进一个房子(可以路过房子而不进),每走一步花费1美金,求所有人都进入房子的最小花费,这是典型的二分图带权匹配问题。

         这题就是建图有点麻烦,但绝不抽象,直接用BFS遍历每个人到所有房子的距离,遍历出一个就拉一条人到房子有向边,建完图就是套模板了。

         注意:KM算法是求最大权匹配的,要求最小权就要把所有边取相反数,最后结果再取相反数,但这只能是完美匹配,不完美匹配还要变一些。

        

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<vector>
      4 #include<queue>
      5 #include<iostream>
      6 #define maxn 500
      7 
      8 using namespace std;
      9 
     10 
     11 char group[101][101];
     12 int index[101][101];
     13 struct pos
     14 {
     15     int x,y;
     16 }people[maxn],house[maxn];
     17 struct edge
     18 {
     19     int to,cap;
     20 };
     21 vector<edge> g[maxn];
     22 int a,b,sum_m,sum_h;
     23 
     24 const int mir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
     25 int vis[101][101];
     26 struct step
     27 {
     28     int x,y,s;
     29 };
     30 void init()
     31 {
     32     sum_m=sum_h=0;
     33     memset(people,0,sizeof(people));
     34     memset(house,0,sizeof(house));
     35     memset(index,0,sizeof(index));
     36     for(int i=0;i<maxn;i++)
     37         g[i].clear();
     38 }
     39 void add_edge(int from,int to,int cap)
     40 {
     41     g[from].push_back((edge){to,cap});
     42 }
     43 void bfs(int sx,int sy,int ex,int ey)
     44 {
     45     memset(vis,0,sizeof(vis));
     46     step now,next;
     47     queue<step> q;
     48     now.x=sx,now.y=sy,now.s=0;
     49     vis[sx][sy]=1;
     50     q.push(now);
     51     while(!q.empty())
     52     {
     53         now=q.front();
     54         q.pop();
     55         if(now.x==ex&&now.y==ey)
     56         {
     57             add_edge(index[sx][sy],index[now.x][now.y],~now.s+1);
     58             return;
     59         }
     60         for(int i=0;i<4;i++)
     61         {
     62             int x=now.x+mir[i][0];
     63             int y=now.y+mir[i][1];
     64             if(x>=0&&y>=0&&x<a&&y<b)
     65             {
     66                 if(!vis[x][y])
     67                 {
     68                     vis[x][y]=1;
     69                     next.x=x,next.y=y,next.s=now.s+1;
     70                     q.push(next);
     71                 }
     72             }
     73         }
     74     }
     75 }
     76 int x[maxn], y[maxn], link[maxn],sx[maxn], sy[maxn];
     77 int slack;
     78 int DFS(int t)
     79 {
     80     int i, tmp;
     81     sx[t] = 1;
     82     for (i = 0; i < g[t].size(); i++)
     83     {
     84         edge e=g[t][i];
     85         if (!sy[e.to])
     86         {
     87             tmp = x[t] + y[e.to] - e.cap;
     88             if (tmp == 0)
     89             {
     90                 sy[e.to] = 1;
     91                 if (link[e.to] == -1 || DFS(link[e.to]))
     92                 {
     93                     link[e.to] = t;
     94                     return 1;
     95                 }
     96             }
     97             else if (tmp < slack)
     98                 slack = tmp;
     99         }
    100     }
    101     return 0;
    102 }
    103 void KM()
    104 {
    105     int i, j;
    106     for(int w=0;w<sum_m;w++)
    107     {
    108         x[w]=0;
    109         for(int v=0;v<g[w].size();v++)
    110         {
    111             if(g[w][v].cap>x[w])
    112                 x[w]=g[w][v].cap;
    113         }
    114     }
    115     for (j = 0; j < sum_h; j++)
    116     {
    117         y[j] = 0;
    118     }
    119     memset(link, -1, sizeof(link));
    120     for (i = 0; i < sum_m; i++)
    121     {
    122         while (1)
    123         {
    124             memset(sx, 0, sizeof(sx));
    125             memset(sy, 0, sizeof(sy));
    126             slack = 0xfffffff;
    127             if (DFS(i)) break;
    128             for (j = 0; j < sum_m; j++)
    129             {
    130                 if (sx[j])
    131                     x[j] -= slack;
    132             }
    133             for (j = 0; j < sum_h; j++)
    134             {
    135                 if (sy[j])
    136                     y[j] += slack;
    137             }
    138         }
    139     }
    140 }
    141 
    142 int main()
    143 {
    144     while(scanf("%d%d",&a,&b)!=EOF,a&&b)
    145     {
    146         getchar();
    147         init();
    148         for(int i=0;i<a;i++)
    149         {
    150             gets(group[i]);
    151             for(int j=0;j<b;j++)
    152             {
    153                 if(group[i][j]=='m')
    154                 {
    155                     people[sum_m].x=i;
    156                     people[sum_m].y=j;
    157                     index[i][j]=sum_m;
    158                     sum_m++;
    159                 }
    160                 else if(group[i][j]=='H')
    161                 {
    162                     house[sum_h].x=i;
    163                     house[sum_h].y=j;
    164                     index[i][j]=sum_h;
    165                     sum_h++;
    166                 }
    167             }
    168         }
    169         for(int n=0;n<sum_m;n++)
    170         {
    171             for(int m=0;m<sum_h;m++)
    172             {
    173                 bfs(people[n].x,people[n].y,house[m].x,house[m].y);
    174             }
    175         }
    176   /*     for(int i=0;i<sum_m;i++)
    177         {
    178             cout<<i<<" ";
    179             for(int j=0;j<g[i].size();j++)
    180                 cout<<g[i][j].to<<" "<<g[i][j].cap<<endl;
    181         }*/
    182         KM();
    183         int ans=0;
    184         int coun = 0,t=0;
    185         for (int i = 0; i < sum_h; i++)
    186         {
    187             t = link[i];
    188             if (t >= 0)
    189             {
    190                 coun ++;
    191                 ans += g[t][i].cap;
    192             }
    193         }
    194         printf("%d
    ",~ans+1);
    195     }
    196     return 0;
    197 }
    View Code
  • 相关阅读:
    树与树的表示
    队列的顺序/链式存储实现
    堆栈的链式存储实现
    堆栈的顺序存储实现
    线性表的链式存储求表长,查找,插入,删除
    C语言博客作业--函数
    C语言博客作业--嵌套循环
    C语言第三次博客作业---单层循环结构
    C语言第二次博客作业---分支结构
    C语言第一次博客作业——输入输出格式
  • 原文地址:https://www.cnblogs.com/liboyan/p/4444096.html
Copyright © 2011-2022 走看看