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\n",~ans+1);

195     }

196     return 0;

197 }
View Code

 

你可能感兴趣的:(poj)