原文地址:http://nuoyanli.com/contest_hdu_multi-university-training-contest-1-1005/
给你一个有向图,1到n的最短路可能有多条,需要你删去一些边使得1到n的最短路严格变长。
删掉边的费用为边的长度,求最小花费。
读懂题后,思考了一阵发现是以最小的代价破坏最短路,翻板子之后发现是最短路+最小割
首先将最短路的所有边存下来(最短路可能有多条),然后利用这些边建图,求新图的1到n的最小割。搞了好久,种于改好了板子,签到了!!!
最短路+最小割居然是签到题。当然榜有一点点歪,不过总体难度算是很难了。
ps:刘老师说先上辣椒水,再上老虎凳
#include
#define endl "\n"
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll maxn = 1e4 + 5;
ll head[maxn], Header[maxn], vis[maxn], length[maxn], gap[maxn];
ll n, m, tot, step;
struct Node1 {
ll to;
ll cap;
ll next;
} edge[4 * maxn];
struct Node2 {
ll to, next;
ll length;
} Edges[maxn];
// 记录每个点的最短距离
void spfa(ll s) {
memset(vis, 0, sizeof(vis));
memset(length, INF, sizeof(length));
queue<ll> q;
q.push(s);
vis[s] = 1;
length[s] = 0;
while (!q.empty()) {
ll u = q.front();
q.pop();
vis[u] = 0;
for (ll i = Header[u]; i != -1; i = Edges[i].next) {
ll v = Edges[i].to;
if (length[v] > length[u] + Edges[i].length) {
length[v] = length[u] + Edges[i].length;
if (!vis[v]) {
vis[v] = 1;
q.push(v);
}
}
}
}
}
struct Sap {
void init() {
memset(head, -1, sizeof(head));
tot = 0;
}
void add(ll u, ll v, ll cap) {
edge[tot].to = v, edge[tot].cap = cap, edge[tot].next = head[u], head[u] = tot++;
edge[tot].to = u, edge[tot].cap = 0, edge[tot].next = head[v], head[v] = tot++;//反向边
}
ll DFS(ll u, ll s, ll t, ll num) {
if (u == t) return num;
ll v;
ll f, minlength = step - 1, flow = 0;
for (ll i = head[u]; i != -1; i = edge[i].next) {
v = edge[i].to;
if (edge[i].cap <= 0) continue;
if (length[v] + 1 == length[u]) {
f = DFS(v, s, t, min(edge[i].cap, num - flow));
edge[i].cap -= f;
edge[i ^ 1].cap += f;
flow += f;
if (flow == num) {
break;
}
if (length[s] >= step) return flow;
}
minlength = min(length[v], minlength);
}
if (flow == 0) {
if (--gap[length[u]] == 0) {
length[s] = step;
}
length[u] = minlength + 1;
gap[length[u]]++;
}
return flow;
}
void create() {
for (ll i = 1; i <= n; i++) {
for (ll j = Header[i]; j != -1; j = Edges[j].next) {
if (length[i] + Edges[j].length == length[Edges[j].to]) {
add(i, Edges[j].to, Edges[j].length);
}
}
}
}
ll maxINFlow(ll s, ll t) {
ll sum = 0;
memset(length, 0, sizeof(length));
memset(gap, 0, sizeof(gap));
gap[0] = step;
while (length[s] < step) {
sum += DFS(s, s, t, INF);
}
return sum;
}
} sap;
//邻接表存图
void Add(ll a, ll b, ll c) {
Edges[step].next = Header[a];
Edges[step].to = b;
Edges[step].length = c;
Header[a] = step++;
}
int main() {
ios::sync_with_stdio(0);
ll a, b, c;
int t;
cin >> t;
while (t--) {
memset(Header, -1, sizeof(Header));
cin >> n >> m;
step = 0;
for (ll i = 0; i < m; i++) {
cin >> a >> b >> c;
Add(a, b, c);
}
step = n;
spfa(1);
sap.init();
sap.create();
cout << sap.maxINFlow(1, n) << endl;
}
return 0;
}