HDU 5294 Tricks Device 最短路+最大流
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5294
题意:
给你个无向图:
1、求最少删除几条边就能破坏节点1到节点n的最短路径,
2、最多能删除多少条边同时保证1到n的最短距离不变。
题解:
首先用spfa或dijcstra跑出所有最短路组成的DAG图。
用这个图跑最大流节能解决第一个问题,用这个图跑一遍bfs最短路就能解决第二个问题。
然而我在跑最大流的时候竟然把DAG图建成双向的了orz。。
代码:
#include<iostream> #include<cstdio> #include<vector> #include<utility> #include<queue> #include<cstring> using namespace std; const int maxn = 2222; const int INF = 0x3f3f3f3f; struct Edge { int u, v, c, f; Edge(int u, int v, int c, int f) :u(u), v(v), c(c), f(f) {} Edge() {} }; struct Dinic { int n, m, s, t; vector<Edge> egs; 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(); egs.clear(); } void addEdge(int u, int v, int c) { egs.push_back(Edge(u, v, c, 0)); egs.push_back(Edge(v, u, 0, 0)); m = egs.size(); G[u].push_back(m - 2); G[v].push_back(m - 1); } bool bfs() { memset(vis, 0, sizeof(vis)); queue<int> Q; Q.push(s); d[s] = 0; vis[s] = 1; while (!Q.empty()) { int x = Q.front(); Q.pop(); for (int i = 0; i < G[x].size(); i++) { Edge& e = egs[G[x][i]]; if (!vis[e.v] && e.c>e.f) { vis[e.v] = 1; d[e.v] = d[x] + 1; Q.push(e.v); } } } return vis[t]; } int dfs(int x, int a) { if (x == t || a == 0) return a; int flow = 0, f; for (int& i = cur[x]; i < G[x].size(); i++) { Edge& e = egs[G[x][i]]; if (d[x] + 1 == d[e.v] && (f = dfs(e.v, min(a, e.c - e.f)))>0) { e.f += f; egs[G[x][i] ^ 1].f -= f; flow += f; a -= f; if (a == 0) break; } } return flow; } int Maxflow(int s, int t) { this->s = s; this->t = t; int flow = 0; while (bfs()) { memset(cur, 0, sizeof(cur)); flow += dfs(s, INF); } return flow; } }dinic; int n, m; vector<pair<int, int> > G[maxn]; vector<pair<int,int> > pre[maxn]; int inq[maxn], d[maxn]; void spfa() { queue<int> Q; memset(inq, 0, sizeof(inq)); memset(d, 0x3f, sizeof(d)); d[0] = 0; inq[0] = 1; Q.push(0); while (!Q.empty()) { int u = Q.front(); Q.pop(); inq[u] = 0; for (int i = 0; i < G[u].size(); i++) { int v = G[u][i].first, w = G[u][i].second; if (d[v] > d[u] + w) { d[v] = d[u] + w; pre[v].clear(); pre[v].push_back(make_pair(u,w)); if (!inq[v]) { Q.push(v); inq[v] = 1; } } else if (d[v] == d[u] + w) { pre[v].push_back(make_pair(u,w)); } } } } int dp[maxn]; int bfs() { memset(dp, -1, sizeof(dp)); queue<int> Q; Q.push(n - 1); dp[n - 1] = 0; while (!Q.empty()) { int u = Q.front(); Q.pop(); for (int i = 0; i < pre[u].size(); i++) { int v = pre[u][i].first; if (dp[v] == -1) { dp[v] = dp[u] + 1; Q.push(v); } } } return dp[0]; } void init() { dinic.init(n); for (int i = 0; i < n; i++) G[i].clear(),pre[i].clear(); } int main() { while (scanf("%d%d", &n, &m) == 2 && n) { init(); for (int i = 0; i < m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); u--, v--; G[u].push_back(make_pair(v, w)); G[v].push_back(make_pair(u, w)); } spfa(); for (int i = n - 1; i > 0; i--) { for (int j = 0; j < pre[i].size(); j++) { int v = pre[i][j].first; //最后建出来的图应该是DAG图! //dinic.addEdge(i, v, 1); dinic.addEdge(v, i, 1); } } int ans1 = dinic.Maxflow(0,n-1); int ans2 = m-bfs(); printf("%d %d\n", ans1,ans2); } return 0; } /* 8 9 1 2 2 2 3 2 2 4 1 3 5 3 4 5 4 5 8 1 1 6 2 6 7 5 7 8 2 3 3 1 2 1 1 3 1 2 3 1 3 4 1 2 1 2 3 0 1 3 2 1 3 3 */