0
点赞
收藏
分享

微信扫一扫

POJ2195费用流+BFS建图

五殳师兄 2022-07-27 阅读 31

题意:
      给你一个n*m的地图,上面有w个人,和w个房子,每个人都要进房子,每个房子只能进一个人,问所有人都进房子的路径总和最少是多少?


思路:
      比较简单的最大流,直接建立两排,左边人,右边房子,广搜或者深搜求距离建图,然后一边费用流就行了,比较简单,没啥说的地方,就这样。
   

#include<queue>

#include<stdio.h>

#include<string.h>



#define N_node 200 + 10

#define N_edge (200 * 200 + 200 ) * 2 + 100

#define INF 1000000000



using namespace std;



typedef struct

{

int from ,to ,cost ,flow ,next;

}STAR;



typedef struct

{

int x ,y ,t;

}NODE;



STAR E[N_edge];

NODE xin ,tou;

int list[N_node] ,tot;

int s_x[N_node];

int mer[N_node];

int map[102][102] ,n ,m;

int dir[4][2] = {0 ,1 ,0 ,-1 ,1 ,0 ,-1 ,0};



void add(int a ,int b ,int c ,int d)

{

E[++tot].from = a;

E[tot].to = b;

E[tot].cost = c;

E[tot].flow = d;

E[tot].next = list[a];

list[a] = tot;





E[++tot].from = b;

E[tot].to = a;

E[tot].cost = -c;

E[tot].flow = 0;

E[tot].next = list[b];

list[b] = tot;

}



bool SPFA(int s ,int t ,int n)

{

for(int i = 0 ;i <= n ;i ++)

s_x[i] = INF;

bool mark[N_node] = {0};

queue<int>q;

q.push(s);

mark[s] = 1;

s_x[s] = 0;

memset(mer ,255 ,sizeof(mer));

while(!q.empty())

{

int xin ,tou;

tou = q.front();

q.pop();

mark[tou] = 0;

for(int k = list[tou] ;k ;k = E[k].next)

{

xin = E[k].to;

if(s_x[xin] > s_x[tou] + E[k].cost && E[k].flow)

{

s_x[xin] = s_x[tou] + E[k].cost;

mer[xin] = k;

if(!mark[xin])

{

mark[xin] = 1;

q.push(xin);

}

}

}

}

return mer[t] != -1;

}





int M_C_Flow(int s ,int t ,int n)

{

int mincost = 0 ,maxflow = 0 ,minflow;

while(SPFA(s ,t ,n))

{

minflow = INF;

for(int i = mer[t] ;i + 1 ;i = mer[E[i].from])

if(minflow > E[i].flow) minflow = E[i].flow;

for(int i = mer[t] ;i + 1 ;i = mer[E[i].from])

{

E[i].flow -= minflow;

E[i^1].flow += minflow;

mincost += E[i].cost;

}

maxflow += minflow;

}

return mincost;

}





void BFS_Buid(int x ,int y ,int N)

{

xin.x = x ,xin.y = y ,xin.t = 0;

int mark[105][105] = {0};

queue<NODE>q;

mark[x][y] = 1;

q.push(xin);

while(!q.empty())

{

tou = q.front();

q.pop();

if(map[tou.x][tou.y] > N)

add(map[x][y] ,map[tou.x][tou.y] ,tou.t ,INF);

for(int i = 0 ;i < 4 ;i ++)

{

xin.x = tou.x + dir[i][0];

xin.y = tou.y + dir[i][1];

xin.t = tou.t + 1;

if(xin.x >= 1 && xin.x <= n && xin.y >= 1 && xin.y <= m && !mark[xin.x][xin.y])

{

mark[xin.x][xin.y] = 1;

q.push(xin);

}

}

}

return ;

}



int main ()

{

int i ,j;

char str[105][105];

while(~scanf("%d %d" ,&n ,&m) && n + m)

{

int M = 0 ,H = 0 ,N = 0;

for(i = 1 ;i <= n ;i ++)

{

scanf("%s" ,str[i]);

for(j = 0 ;j < m ;j ++)

if(str[i][j] == 'm')

N ++;

}

for(i = 1 ;i <= n ;i ++)

{

for(j = 1 ;j <= m ;j ++)

{

if(str[i][j-1] == '.') map[i][j] = 0;

else if(str[i][j-1] == 'm') map[i][j] = ++M;

else

{

++H;

map[i][j] = H + N;

}

}

}

memset(list ,0 ,sizeof(list)) ,tot = 1;

for(i = 1 ;i <= N ;i ++)

add(0 ,i ,0 ,1) ,add(i + N ,N + N + 1 ,0 ,1);

for(i = 1 ;i <= n ;i ++)

for(j = 1 ;j <= m ;j ++)

{

if(map[i][j] && map[i][j] <= N)

BFS_Buid(i ,j ,N);

}

printf("%d\n" ,M_C_Flow(0 ,N + N + 1 ,N + N + 1));

}

return 0;

}
























举报

相关推荐

0 条评论