Ranking (as of 2014-06-22): 274 out of 668
Language: C++
/* UVa 670 - The dog task To build using Visual Studio 2012: cl -EHsc -O2 UVa_670_The_dog_task.cpp */ #include <iostream> #include <vector> #include <queue> #include <utility> #include <algorithm> #include <cmath> 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 point { int x_, y_; }; double euclidean_distance(const point& a, const point& b) { double dx = static_cast<double>(a.x_ - b.x_), dy = static_cast<double>(a.y_ - b.y_); return sqrt(dx * dx + dy * dy); } int main() { int l; cin >> l; while (l--) { int n, m; cin >> n >> m; vector<point> routes(n), places(m); for (int i = 0; i < n; i++) cin >> routes[i].x_ >> routes[i].y_; vector<double> route_distances(n - 1); for (int i = 0; i < n - 1; i++) route_distances[i] = euclidean_distance(routes[i], routes[i + 1]); for (int i = 0; i < m; i++) cin >> places[i].x_ >> places[i].y_; int nr_vertices = n + m + 2; vector< vector<edge> > graph(nr_vertices); // indices are: // 0 - (m - 1): Ralph's interesting place vertices // m - (m + n - 1) : Bob's route vertices, // i-th vertex represents the path from (x(i), y(i)) to (x(i + 1), y(i + 1)) // n + m: source vertex, n + m + 1: sink vertex int source = n + m, sink = n + m + 1; for (int i = 0; i < m; i++) { // append the edges between the source and place vertices graph[source].push_back(edge(i, 1, 1)); graph[i].push_back(edge(source, 1, 0)); for (int j = 0; j < n - 1; j++) { // append the edges between place vertices and route vertices if (euclidean_distance(places[i], routes[j]) + euclidean_distance(places[i], routes[j + 1]) <= 2.0 * route_distances[j]) { graph[i].push_back(edge(m + j, 1, 1)); graph[m + j].push_back(edge(i, 1, 0)); } } } for (int i = m; i < m + n; i++) { // append the edges between route vertices and the sink graph[i].push_back(edge(sink, 1, 1)); graph[sink].push_back(edge(i, 1, 0)); } netflow(graph, source, sink); // apply Ford-Fulkerson's augmenting path algorithm cout << n + total_flow(graph, source) << endl; for (int i = 0; i < n - 1; i++) { if (i) cout << ' '; cout << routes[i].x_ << ' ' << routes[i].y_; const vector<edge>& edges = graph[m + i]; int j = -1; for (size_t k = 0; k < edges.size(); k++) if (edges[k].residual && edges[k].v < m) { j = edges[k].v; break; } if (j != -1) cout << ' ' << places[j].x_ << ' ' << places[j].y_; } cout << ' ' << routes[n - 1].x_ << ' ' << routes[n - 1].y_ << endl; if (l) cout << endl; } return 0; }
No comments:
Post a Comment