题目大意:有很多只小动物要从左上角跑到右下角,给出每条线路所需的人手,问至少需要多少人手,才能将所有动物抓住
解题思路:最小割,就是最小割,但是用最大流处理不了,边太多了
具体可以参考算法合集之《浅析最大最小定理在信息学竞赛中的应用》
知道了这个后,这题估计就可以解了
给出我的建图方式
将每一个小三角形从左往右,从上到下依次编号为1-2-3。。
每行的同一个三角行的编号差就是2 * (m - 1)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 1111 * 1111 * 3;
#define INF 0x3f3f3f3f
struct Edge{
int to, next, dist;
}E[N<<2];
struct Node {
int id, val;
Node(int id, int val): id(id), val(val) {}
bool operator < (const Node &a) const {
return val > a.val;
}
};
int head[N], d[N];
int tot, source, sink, n, m;
bool inq[N];
void AddEdge(int from, int to, int dist) {
E[tot].to = to;
E[tot].dist = dist;
E[tot].next = head[from];
head[from] = tot++;
}
void init() {
memset(head, -1, sizeof(head));
tot = 0;
source = 2 * (m - 1) * (n - 1) + 2;
sink = source - 1;
int u, v, d;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m - 1; j++) {
scanf("%d", &d);
if (i == 1) {
u = j * 2;
AddEdge(sink, u, d);
AddEdge(u, sink, d);
}
else if(i == n) {
u = 2 * (m - 1) * (i - 2) + 2 * (j - 1) + 1;
AddEdge(source, u, d);
AddEdge(u, source, d);
}
else {
u = 2 * (m - 1) * (i - 2) + 2 * (j - 1) + 1;
v = u + 2 * (m - 1) + 1;
AddEdge(u, v, d);
AddEdge(v, u, d);
}
}
for (int i = 1; i <= n - 1; i++)
for (int j = 1; j <= m; j++) {
scanf("%d", &d);
if (j == 1) {
u = 2 * (m - 1) * (i - 1) + 1;
AddEdge(u, source, d);
AddEdge(source, u, d);
}
else if(j == m) {
u = 2 * (m - 1) * i;
AddEdge(u, sink, d);
AddEdge(sink, u, d);
}
else {
u = 2 * (m - 1) * (i - 1) + 2 * (j - 1);
v = u + 1;
AddEdge(u, v, d);
AddEdge(v, u, d);
}
}
for (int i = 1; i <= n - 1; i++)
for (int j = 1; j <= m - 1; j++) {
scanf("%d", &d);
u = 2 * (m - 1) * (i - 1) + 2 * (j - 1) + 1;
v = u + 1;
AddEdge(u, v, d);
AddEdge(v, u, d);
}
}
void BFS() {
priority_queue<Node> q;
memset(inq, 0, sizeof(inq));
for (int i = 1; i <= sink; i++)
d[i] = INF;
int u;
d[source] = 0;
q.push(Node(source, 0));
while (!q.empty()) {
Node cur = q.top();
q.pop();
int u = cur.id;
if (inq[u])
continue;
inq[u] = true;;
for (int i = head[u]; i != -1; i = E[i].next) {
int v = E[i].to;
if (d[v] > d[u] + E[i].dist) {
d[v] = d[u] + E[i].dist;
q.push(Node(v, d[v]));
}
}
}
}
int main() {
int cas = 1;
while (scanf("%d%d", &n, &m) != EOF && n + m) {
init();
BFS();
printf("Case %d: Minimum = %d\n", cas++, d[sink]);
}
return 0;
}