![]()

故纸堆:桌上有n张幻灯片杂乱地叠在一起,给出每张幻灯片的边界和页码坐标,求在不翻动的情况下哪些页码可以确定?
3.5借助水流解决问题的网络流
二分图匹配
如果页码u坐标落在幻灯片v内,则建立一条边(u,v),在完全图上跑二分图匹配必然完美,如果删掉某一条边后变不完美了,说明这条边的对应关系是确定的。
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
#define MAX_N 26
////////////////////////最大流开始//////////////////////////////////////
#define MAX_V MAX_N * 2
int V; // 顶点数
vector<int> G[MAX_V]; // 图的邻接表
int match[MAX_V]; // 所匹配的顶点
bool used[MAX_V]; // DFS中用到的访问标记
// 向图中增加一条连接u和v的边
void add_edge(int u, int v)
{
G[u].push_back(v);
G[v].push_back(u);
}
// 通过DFS寻找增广路
bool dfs(int v)
{
used[v] = true;
for (vector<int>::iterator it = G[v].begin(); it != G[v].end(); ++it)
{
int u = *it, w = match[u];
if (w < 0 || !used[w] && dfs(w))
{
match[v] = u;
match[u] = v;
return true;
}
}
return false;
}
// 求解二分图的最大匹配
int bipartite_matching()
{
int res = 0;
memset(match, -1, sizeof(match));
for (int v = 0; v < V; ++v)
{
if (match[v] < 0)
{
memset(used, 0, sizeof(used));
if (dfs(v))
{
++res;
}
}
}
return res;
}
void clear()
{
for (int i = 0; i < V; ++i)
{
G[i].clear();
}
}
///////////////////////////////最大流结束/////////////////////////////////////
struct Point
{
int x, y;
}P[MAX_N];
struct Slide
{
int xmin, xmax, ymin, ymax;
bool contain(const Point& p)
{
return xmin < p.x && p.x < xmax && ymin < p.y && p.y < ymax;
}
} S[MAX_N];
///////////////////////////SubMain//////////////////////////////////
int main(int argc, char *argv[])
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int n, id = 0;
while (scanf("%d", &n) && n)
{
V = 2 * n;
for (int i = 0; i < n; ++i)
{
scanf("%d%d%d%d", &S[i].xmin, &S[i].xmax, &S[i].ymin, &S[i].ymax);
}
for (int i = 0; i < n; ++i)
{
scanf("%d%d", &P[i].x, &P[i].y);
}
int slide_id[MAX_N];
memset(slide_id, -1, sizeof(slide_id));
for (int i = 0; i < n; ++i)
{
int match_count = 0;
for (int k = 0; k < n; ++k)
{
if (S[i].contain(P[k])) // 删掉掉i->k这个边
{
clear();
for (int j = 0; j < n; ++j)
{
if (i != j)
{
for (int l = 0; l < n; ++l)
{
if (k != l)
{
if (S[j].contain(P[l]))
{
add_edge(j, n + l);
}
}
}
}
}
if (bipartite_matching() == n - 1) // 发现匹配变得不完美了,说明它是确定的
{
++match_count;
slide_id[i] = k;
}
}
}
if (match_count != 1)
{
slide_id[i] = -1;
}
}
printf("Heap %d\n", ++id);
bool has_one = false;
for (int i = 0; i < n; ++i)
{
if (slide_id[i] != -1)
{
printf("%s(%c,%d)", (has_one ? " " : ""), i + 'A', slide_id[i] + 1);
has_one = true;
}
}
if (has_one)
{
puts("");
}
else
{
puts("none");
}
puts("");
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
system("out.txt");
#endif
return 0;
}
///////////////////////////End Sub//////////////////////////////////
| 13789012 | hankcs | 1486 | Accepted | 180K | 0MS | C++ | 3062B | 2015-01-17 23:58:43 |
知识共享署名-非商业性使用-相同方式共享:码农场 » POJ 1486 Sorting Slides 题解 《挑战程序设计竞赛》
码农场