Uva 11146 Insurrection(最短路+最小割)

来源:互联网 发布:cnc编程要学多久 编辑:程序博客网 时间:2024/06/05 07:46

题目地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2087

思路:

1.删除k个点使得点1到点n不连通。

2.拆点。将每个点拆为i和i’,容量为删除该点的花费(即为从1点到该点的最短路+n点到该点的最短路)。

3.对于原图中的无向边i-j,连边i'->j,j'->i,容量均为正无穷。则答案即为点1到点n的最大流(即最小割)。

4.当最大流大于等于INF时,无解。也即为点1和点n直接有边相连。

#include<queue>#include<cmath>#include<cstdio>#include<vector>#include<cstring>#include<iostream>#include<algorithm>#define debugusing namespace std;const double eps = 1e-6;const int maxn = 2000 + 50;const int maxm = 2000 + 50;const int INF = 0x3f3f3f3f;struct Edge{int from, to;double cap, flow;Edge(int a, int b, double c, double d) :from(a), to(b), cap(c), flow(d) {}};int dcmp(double x){if (fabs(x) < eps) return 0;else return x < 0 ? -1 : 1;}struct Dinic{int n, m, s, t;vector<Edge> edges;vector<int> G[maxn];bool vis[maxn];int d[maxn];int cur[maxn];void init(int n){this->n = n;for (int i = 0; i <= n; i++) G[i].clear();edges.clear();}void addEdge(int from, int to, double cap){edges.push_back(Edge(from, to, cap, 0));edges.push_back(Edge(to, from, 0, 0));m = edges.size();G[from].push_back(m - 2);G[to].push_back(m - 1);}bool BFS(){memset(vis, 0, sizeof(vis));queue<int> Q;Q.push(s);vis[s] = 1;d[s] = 0;while (!Q.empty()){int x = Q.front();Q.pop();for (int i = 0; i < G[x].size(); i++){Edge& e = edges[G[x][i]];if (!vis[e.to] && dcmp(e.cap - e.flow)>0){vis[e.to] = 1;d[e.to] = d[x] + 1;Q.push(e.to);}}}return vis[t];}double DFS(int x, double a){if (x == t || dcmp(a) == 0) return a;double flow = 0, f;for (int& i = cur[x]; i < G[x].size(); i++){Edge& e = edges[G[x][i]];if (d[x] + 1 == d[e.to] && (dcmp(f = DFS(e.to, min(a, e.cap - e.flow)))) > 0){e.flow += f;edges[G[x][i] ^ 1].flow -= f;flow += f;a -= f;if (dcmp(a) == 0) break;}}return flow;}double MaxFlow(int s, int t){this->s = s;this->t = t;double flow = 0;while (BFS()){memset(cur, 0, sizeof(cur));flow += DFS(s, INF);}return flow;}};struct E{int nt, to;};Dinic g;queue<int> q;E edge[maxm];int head[maxn];int n, m, S, T;double w[maxn];int vis[maxn], tot;double dist[2][maxn];void addEdge(int u, int v){edge[tot].to = v, edge[tot].nt = head[u],head[u] = tot++;}void mindist(int s, int id){while (!q.empty()) q.pop();memset(vis, 0, sizeof(vis));for (int i = 0; i <= n; i++) dist[id][i] = INF;q.push(s), vis[s] = 1, dist[id][s] = 0;while (!q.empty()){int now = q.front();q.pop(), vis[now] = 0;for (int i = head[now]; ~i; i = edge[i].nt){int nt = edge[i].to;if (dcmp(dist[id][nt] -(dist[id][now] + w[nt]))>0){dist[id][nt] = dist[id][now] + w[nt];if (!vis[nt]){vis[nt] = 1;q.push(nt);}}}}}void init(){tot = 0;memset(w, 0, sizeof(w));memset(head, -1, sizeof(head));g.init(2*n + 1);}int main(){#ifdef  debufreopen("in.txt", "r", stdin);#endif //  debug int t;scanf("%d", &t);while (t--){scanf("%d%d", &n, &m);init();for (int i = 2; i <= n - 1; i++){scanf("%lf", &w[i]);}for (int i = 0; i < m; i++){int x, y;scanf("%d%d", &x, &y);addEdge(x, y);addEdge(y, x);}mindist(1, 0);mindist(n, 1);S = 1, T =n;for (int i = 1; i <= n; i++){if (i != 1 && i != n){g.addEdge(i, i + n, dist[0][i] + dist[1][i]);}for (int j = head[i]; ~j; j = edge[j].nt){int nt = edge[j].to;if (i != 1 && i != n){g.addEdge(i + n, nt, INF);}else{g.addEdge(i, nt, INF);}}}double ans = g.MaxFlow(S, T);if(ans>=INF)printf("No Solution!\n");else printf("%.4f\n", ans);}return 0;}





原创粉丝点击