HDU 3416 Marriage Match IV【最短路 + 最大流】经典模型好题
2018-02-13 17:04
405 查看
传送门
题意: 给定一幅单向图(n, m), 起点和终点, 问起点到终点有所少条最短路径, 每条边只能做一遍.
思路: 如果没有只走一遍的限制, 那么就是个很简单的最短路了. 关键在于只能走一遍. 那么我们就想跑最短路吧图中有用的边先存下来, 重新建图, 让每条边的流量的为1, 然后跑s - t 的最大流就是ans. 有用的边为(假设dis1表示从s出发的最短路, dis2表示t出发的最短路.) 那么就是dis1[u] + w + dis2[v] = dis1[t], 然后就是上板子即可, 主要是这个模型很重要, 边只能经过一次那么我们就设流量为1, 那就是最大流. 这种模型才是本道题的精华所在.
AC Code
题意: 给定一幅单向图(n, m), 起点和终点, 问起点到终点有所少条最短路径, 每条边只能做一遍.
思路: 如果没有只走一遍的限制, 那么就是个很简单的最短路了. 关键在于只能走一遍. 那么我们就想跑最短路吧图中有用的边先存下来, 重新建图, 让每条边的流量的为1, 然后跑s - t 的最大流就是ans. 有用的边为(假设dis1表示从s出发的最短路, dis2表示t出发的最短路.) 那么就是dis1[u] + w + dis2[v] = dis1[t], 然后就是上板子即可, 主要是这个模型很重要, 边只能经过一次那么我们就设流量为1, 那就是最大流. 这种模型才是本道题的精华所在.
AC Code
const int maxn = 1e3 + 5; const int maxm = 1e5+5; int head1[maxn], cnt1; int n, m, s, t; bool vis1[maxn]; int d[maxn], cur[maxn]; struct node1 { int u, v; int cap, flow, next; } e[maxm*2]; //因为是双向边 所以记得开二倍 void init1() { cnt1 = 0; Fill(head1, -1); } void add1(int u, int v, int c, int f) { e[cnt1] = node1{u, v, c, f, head1[u]}; head1[u] = cnt1++; } bool BFS() { queue<int> q; q.push(s); Fill(vis1,0); vis1[s] = 1; d[s] = 0; while (!q.empty()) { int u = q.front(); q.pop(); for (int i = head1[u] ; ~i ; i = e[i].next) { int to = e[i].v; if (!vis1[to] && e[i].cap > e[i].flow) { //只考虑残量网络的弧 vis1[to] = 1; d[to] = d[u] + 1; q.push(to); } } } return vis1[t]; } int dfs(int x, int a) { if (x == t || a == 0) return a; int flow = 0, f; int &i = cur[x]; for (i = head1[x] ; ~i ; i = e[i].next) { //从上次考虑的弧 int to = e[i].v; if (d[to]== d[x] + 1 && (f = dfs(to, min(a, e[i].cap - e[i].flow))) > 0) { e[i].flow += f; e[i^1].flow -= f; flow += f; a -= f; if (a == 0) break; } } return flow; } int Dinic() { int maxflow = 0; while (BFS()) { Fill(cur, 0); maxflow += dfs(s, inf); } return maxflow; } struct node2 { int to, next, w; bool operator < (const node2 & a) const { return w > a.w; } } g[maxm]; int cnt2 , head2[maxn]; void init2() { cnt2 = 0; Fill(head2, -1); } void add2(int u, int v, int w) { g[cnt2] = node2{v, head2[u], w}; head2[u] = cnt2++; } int dis[2][maxn]; int vis2[maxn]; void dij(int st, int id) { priority_queue<node2> q; Fill(dis[id],inf); Fill(vis2,0); dis[id][st] = 0; q.push((node2){st, 0, 0}); while (!q.empty()) { node2 u = q.top(); q.pop(); if(vis2[u.to]) continue; vis2[u.to] = 1; for (int i = head2[u.to]; ~i ; i = g[i].next) { int to = g[i].to; if (dis[id][to] > dis[id][u.to] + g[i].w) { dis[id][to] = dis[id][u.to] + g[i].w; q.push((node2){to, 0, dis[id][to]}); } } } } bool is[maxm]; struct gg { int u, v, w; } pp[maxm]; void solve() { scanf("%d%d", &n, &m); init2(); Fill(is, false); for (int i = 1 ; i <= m ; i ++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); add2(u, v, w); pp[i].u = u; pp[i].v = v; pp[i].w = w; } scanf("%d%d", &s, &t); dij(s, 0); init2(); for (int i = 1 ; i <= m ; i ++) { add2(pp[i].v, pp[i].u, pp[i].w); } dij(t, 1); for (int i = 1 ; i <= m ; i ++) { int tmp = dis[0][pp[i].u]; tmp += pp[i].w + dis[1][pp[i].v]; if (tmp == dis[0][t]) is[i] = true; } init1(); for (int i = 1 ; i <= m ; i ++) { if (!is[i]) continue; add1(pp[i].u, pp[i].v, 1, 0); add1(pp[i].v, pp[i].u, 0, 0); } printf("%d\n", Dinic()); }
相关文章推荐
- HDU 3416 —— Marriage Match IV(最短路+最大流)
- O - Marriage Match IV - hdu 3416(最短路+最大流)
- [HDU 3416]Marriage Match IV[最大流][最短路]
- hdu 3416 Marriage Match IV 【图论-网络流-最短路+最大流(spfa + Dinic)】
- HDU 3416 Marriage Match IV(最短路+最大流)
- hdu 3416 Marriage Match IV 【 最短路 最大流 】
- HDU 3416 Marriage Match IV【最短路+最大流】
- HDU 3416 Marriage Match IV (最短路判断建边+最大流)
- hdu 3416 Marriage Match IV 【网络最大流+最短路】
- HDU_3416_Marriage Match IV(最短路+最大流)
- HDU 3416 Marriage Match IV(最短路+最大流)
- HDU 3416 Marriage Match IV (求最短路的条数,最大流)
- HDU-3416 Marriage Match IV(最大流+最短路)
- HDU-3416 Marriage Match IV(最短路+最大流)
- HDU — 3416 Marriage Match IV(最大流+最短路)
- hdu 3416 Marriage Match IV (最短路+最大流)
- HDU 3416 Marriage Match IV(最短路+最大流)
- HDU-3416 Marriage Match IV(最短路+最大流)
- HDU 3416 Marriage Match IV【SPFA+最大流】
- hdu 3416 Marriage Match IV【SPFA+最大流Dinic】