题意
给一个图,1号点到N号点最短路位L,现在要求删除权值和最小的边,让最短路全部断掉。
思路
让原来的最短路全部断掉,显然一条最短路只要有一个边删掉就可以了,多条最短路构成一个最短路图,割断他的最小代价就是最小割。就是最短路重新建图,然后跑个最大流。
AC代码 C++
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <vector>
#include <functional>
using namespace std;
#define MAXV 1005
struct edge
{
int to, cost, wei;
edge(int t, int c, int w) :to(t), cost(c), wei(w) {}
};
template<class T>
struct Dinic {
const static int N = 2022, M = 20222;
int s, t, n, h[N], cur[N], level[N], q[N], e, ne[M], to[M];
T cap[M], flow;
void liu(int u, int v, T w)
{
to[e] = v;
ne[e] = h[u];
cap[e] = w;
h[u] = e++;
}
void add_edge(int u, int v, T w)
{
liu(u, v, w);
liu(v, u, 0);
}
void init(int _n = N)
{
fill(h, h + _n, -1);
e = 0;
}
bool bfs()
{
int L = 0, R = 0, c, k;
fill(level, level + n, -1);
level[q[R++] = s] = 0;
while (L < R && level[t] == -1)
{
c = q[L++];
for (k = h[c]; ~k; k = ne[k])
if (cap[k] > 0 && level[to[k]] == -1)
level[q[R++] = to[k]] = level[c] + 1;
}
return ~level[t];
}
T dfs(int c, T mx)
{
if (c == t) return mx;
T ret = 0;
for (int &k = cur[c]; ~k; k = ne[k])
if (level[to[k]] == level[c] + 1 && cap[k] > 0)
{
T flow = dfs(to[k], min(mx, cap[k]));
ret += flow; cap[k] -= flow, cap[k ^ 1] += flow; mx -= flow;
if (!mx) return ret;
}
level[c] = -1;
return ret;
}
T max_flow(int _s, int _t, int _n)
{
s = _s, t = _t, n = _n;
flow = 0;
while (bfs())
{
copy(h, h + n, cur);
flow += dfs(s, ~0U >> 1);
}
return flow;
}
};
Dinic<int> di;
vector<edge> g[MAXV];
int d[2][MAXV];
void dijkstra(int s, int* d)
{
int i, v;
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > que;
d[s] = 0;
que.push(pair<int, int>(0, s));
while (!que.empty())
{
pair<int, int> p = que.top();
que.pop();
v = p.second;
if (d[v] < p.first)
continue;
for (i = 0; i<g[v].size(); i++)
{
edge& e = g[v][i];
if (d[e.to]>d[v] + e.cost)
{
d[e.to] = d[v] + e.cost;
que.push(pair<int, int>(d[e.to], e.to));
}
}
}
}
int main()
{
int T, n, m, u, v, w, i, j;
scanf("%d", &T);
while (T-- && scanf("%d%d", &n, &m))
{
for (int i = 0; i <= n; i++)
g[i].clear();
for (int i = 0; i<m; i++)
{
scanf("%d%d%d", &u, &v, &w);
g[u].push_back(edge(v, 1, w));
g[v].push_back(edge(u, 1, w));
}
memset(d, 0x3f, sizeof d);
dijkstra(1, d[0]);
dijkstra(n, d[1]);
di.init(n + 5);
for (i = 1; i <= n; i++)
for (j = 0; j<g[i].size(); j++)
{
v = g[i][j].to;
w = g[i][j].wei;
if (d[0][i] + 1 + d[1][v] == d[0][n])
di.add_edge(i, v, w);
}
printf("%d\n", di.max_flow(1, n, n + 1));
}
return 0;
}