Run Time: 0.000
Ranking (as of 2016-04-17): 58 out of 452
Language: C++
/* UVa 663 - Sorting Slides To build using Visucal Studio 2012: cl -EHsc UVa_663_Sorting_Slides.cpp */ #include <vector> #include <queue> #include <utility> #include <algorithm> #include <cstdio> using namespace std; struct edge { int v; // neighboring vertex int capacity; // capacity of edge int flow; // flow through edge int residual; // residual capacity of edge edge(int _v, int _capacity, int _residual) : v(_v), capacity(_capacity), flow(0), residual(_residual) {} }; struct vertex_state { bool discovered; int parent; vertex_state() : discovered(false), parent(-1) {} }; void bfs(const vector< vector<edge> >& graph, int start, vector<vertex_state>& states) { queue<int> q; states[start].discovered = true; q.push(start); while (!q.empty()) { int u = q.front(); q.pop(); for (int i = 0; i < graph[u].size(); i++) { const edge& e = graph[u][i]; if (e.residual > 0 && !states[e.v].discovered) { states[e.v].discovered = true; states[e.v].parent = u; q.push(e.v); } } } } edge& find_edge(vector< vector<edge> >& graph, int u, int v) { int i; for (i = 0; i < graph[u].size(); i++) if (graph[u][i].v == v) break; return graph[u][i]; } int path_volume(vector< vector<edge> >& graph, int start, int end, const vector<vertex_state>& states) { if (states[end].parent == -1) return 0; edge& e = find_edge(graph, states[end].parent, end); if (start == states[end].parent) return e.residual; else return min(path_volume(graph, start, states[end].parent, states), e.residual); } void augment_path(vector< vector<edge> >& graph, int start, int end, const vector<vertex_state>& states, int volume) { if (start == end) return; edge& e = find_edge(graph, states[end].parent, end); if (e.flow < e.capacity) e.flow += volume; if (e.residual) e.residual -= volume; edge& r= find_edge(graph, end, states[end].parent); if (r.flow) r.flow -= volume; if (r.residual < r.capacity) r.residual += volume; augment_path(graph, start, states[end].parent, states, volume); } void netflow(vector< vector<edge> >& graph, int source, int sink) { while (true) { vector<vertex_state> states(graph.size()); bfs(graph, source, states); int volume = path_volume(graph, source, sink, states); // calculate the volume of augmenting path if (volume > 0) augment_path(graph, source, sink, states, volume); else break; } } int total_flow(const vector< vector<edge> >& graph, int source) { int flow = 0; const vector<edge>& edges = graph[source]; for (int i = 0, e = edges.size(); i < e; i++) flow += edges[i].flow; return flow; } struct slide { int x_min_, x_max_, y_min_, y_max_; }; struct number { int x_, y_; }; void add_edge(int i, int j, vector< vector<edge> >& graph) // add an edge from i to j { graph[i].push_back(edge(j, 1, 1)); graph[j].push_back(edge(i, 1, 0)); } bool number_in_slide(const slide& s, const number& n) { return n.x_ > s.x_min_ && n.x_ < s.x_max_ && n.y_ > s.y_min_ && n.y_ < s.y_max_; } int maximum_bipertite_matching(int n, int esi, int eni, const vector<slide>& slides, const vector<number>& numbers) { int nr_vertices = n * 2 + 2; vector< vector<edge> > graph(nr_vertices); // indices are: // 0 - (n - 1): slide vertices, n - (n * 2 - 1): number vertices, // n * 2: source vertex, (n * 2 + 1): sink vertex int source = n * 2, sink = n * 2 + 1; for (int i = 0; i < n; i++) // add the edges between slide vertices and number vertices if (i != esi) // exclude esi-th slide for (int j = 0; j < n; j++) if (j != eni && // exclude eni-th number number_in_slide(slides[i], numbers[j])) add_edge(i, n + j, graph); for (int i = 0; i < n; i++) { add_edge(source, i, graph); // add an edge from the source vertex to a slide vertex add_edge(n + i, sink, graph); // add an edge from a number vertex to sink vertex } netflow(graph, source, sink); // apply Ford-Fulkerson's augmenting path algorithm return total_flow(graph, source); } int main() { for (int heap_nr = 1; ; heap_nr++) { int n; scanf("%d", &n); if (!n) break; vector<slide> slides(n); for (int i = 0; i < n; i++) scanf("%d %d %d %d", &slides[i].x_min_, &slides[i].x_max_, &slides[i].y_min_, &slides[i].y_max_); vector<number> numbers(n); for (int i = 0; i < n; i++) scanf("%d %d", &numbers[i].x_, &numbers[i].y_); vector<int> unique_matchings(n, -1); for (int i = 0; i < n; i++) // for each slide for (int j = 0; j < n; j++) // for each number if (number_in_slide(slides[i], numbers[j]) && maximum_bipertite_matching(n, i, j, slides, numbers) == n - 1) { // perfect matching if (unique_matchings[i] == -1) unique_matchings[i] = j; else { // not unique unique_matchings[i] = -1; break; } } printf("Heap %d\n", heap_nr); bool none = true; for (int i = 0; i < n; i++) if (unique_matchings[i] != -1) { if (none) none = false; else putchar(' '); printf("(%c,%d)", 'A' + i, unique_matchings[i] + 1); } if (none) printf("none\n\n"); else printf("\n\n"); } return 0; }
No comments:
Post a Comment