标签:超级 cap dde include return scan push tin home
对于每一个H 每一个m编号 然后遍历每一个m 使用BFS求出该m到每一个H的最短距离 然后把边加进图里 超级源点 超级汇点 容量为1 费用为0 跑一遍最小费用流
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; const int MAXN = 10000; const int MAXM = 100000; const int INF = 99999999; char ma[150][150]; int used[150][150]; int no[150][150]; int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0}; int n, m; struct Edge { int to, next, cap, flow, cost; }edge[MAXM]; int head[MAXN], tol; int pre[MAXN], dis[MAXN]; bool vis[MAXN]; int N; void init(int n) { N = n; tol = 0; memset(head, -1, sizeof(head)); } void addedge(int u, int v, int cap, int cost) { edge[tol].to = v; edge[tol].cap = cap; edge[tol].cost = cost; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = 0; edge[tol].cost = -cost; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++; } bool spfa(int s, int t) { queue<int >q; for(int i = 0; i < N; i++) { dis[i] = INF; vis[i] = 0; pre[i] = -1; } dis[s] = 0; vis[s] = 1; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = 0; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost) { dis[v] = dis[u] + edge[i].cost; pre[v] = i; if (!vis[v]) { vis[v] = 1; q.push(v); } } } } if (pre[t] == -1) return 0; else return 1; } int mincostmaxflow(int s, int t, int &cost) { int flow = 0; cost = 0; while(spfa(s, t)) { int Min = INF; for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) { if (Min > edge[i].cap - edge[i].flow) Min = edge[i].cap - edge[i].flow; } for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) { edge[i].flow += Min; edge[i^1].flow -= Min; cost += edge[i].cost * Min; } flow += Min; } return flow; } struct Node { int x, y, w; }; void bfsma(int x, int y) { memset(used, 0, sizeof(used)); queue<Node> q; Node now; now.x = x; now.y = y; now.w = 0; q.push(now); used[now.x][now.y] = 1; while(!q.empty()) { now = q.front(); q.pop(); Node next; for(int i = 0; i < 4; i++) { next.x = now.x + dir[i][0]; next.y = now.y + dir[i][1]; next.w = now.w + 1; if (next.x >= n || next.y >= m || next.x < 0 || next.y < 0) continue; if (used[next.x][next.y]) continue; used[next.x][next.y] = 1; q.push(next); } if (ma[now.x][now.y] == ‘H‘) { //printf("%d %d %d\n", no[x][y], no[now.x][now.y], now.w); addedge(no[x][y], no[now.x][now.y], 1 , now.w); } } } int main() { while(scanf("%d%d", &n, &m) != EOF && n != 0 && m != 0) { int ans; int sp, tp; init(2000); for(int i = 0; i < n; i++) { scanf("%s", ma[i]); } memset(used, 0, sizeof(used)); memset(no, 0, sizeof(no)); int mc = 1; int hc = 1001; sp = 0; tp = 2000-1; for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { if (ma[i][j] == ‘m‘) { no[i][j] = mc++; } if (ma[i][j] == ‘H‘){ no[i][j] = hc++; addedge(no[i][j], tp, 1, 0); } } } for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { if (ma[i][j] == ‘m‘) { addedge(sp, no[i][j], 1, 0);//printf("debug"); bfsma(i, j); } } } mincostmaxflow(sp, tp, ans); cout<<ans<<endl; } return 0; }
标签:超级 cap dde include return scan push tin home
原文地址:https://www.cnblogs.com/16-CHQ/p/8963536.html