Path - 2019 Multi-University Training Contest 1
题意
有一张n个点,m条边的有向图,切边的代价为边权,要求以最小的代价切掉一些边,使最短路变长
思路
先跑一遍Dijkstra,获得最短路,然后依照以下方法构造最短路图
if(dis[u[i]]+w[i] == dis[v[i]]){
addEdge(u[i],v[i],w[i]);
}
其中dis[i]表示第1个点到第i个点的距离,u[i],v[i],w[i]分别为起点,终点,边权
之后就是求这张最短路图的最小割,根据最大流最小割定理,Dinic 跑一遍最大流即可
时间复杂度 O(玄学)
Code
//ItsLucas 2019.07.22
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const long long maxn = 10010;
struct node {
long long v,w;
node(long long v=0,long long w=0): v(v), w(w){};
inline bool operator<(const node &a) const {
return w > a.w;
}
};
vector<node> G[maxn];
ll dis[maxn];
bool vis[maxn];
long long u[maxn],v[maxn],w[maxn];
inline void add(long long u,long long v,long long w) {
G[u].push_back(node(v,w));
}
void init() {
for (long long i = 0; i < maxn; i++) {
G[i].clear();
vis[i] = false;
dis[i] = 1e18;
}
}
void dijkstra(long long s) {
priority_queue<node> Q;
Q.push(node(s,0));
dis[s] = 0;
while(!Q.empty()) {
node now = Q.top();
Q.pop();
long long v = now.v;
if(vis[v]) continue;
vis[v] = true;
for(node i : G[v]) {
long long v2 = i.v;
long long len = i.w;
if(!vis[v2] && dis[v2] > dis[v] + len) {
dis[v2] = dis[v] + len;
Q.push(node(v2,dis[v2]));
}
}
}
}
struct Edge {
long long to, cap;
Edge(long long to, long long cap) : to(to), cap(cap) {}
};
struct Dinic {
const long long INF = 1e18;
long long n, s, t;
vector<Edge> es;
vector<vector<long long> > G;
vector<long long> dis, cur;
Dinic(long long n, long long s, long long t) : n(n), s(s), t(t), G(n + 1), dis(n + 1), cur(n + 1) {}
void addEdge(long long u, long long v, long long cap) {
G[u].push_back(es.size());
es.emplace_back(v, cap);
G[v].push_back(es.size());
es.emplace_back(u, 0);
}
bool bfs() {
dis.assign(n + 1, 0);
queue<long long> q;
q.push(s);
dis[s] = 1;
while (!q.empty()) {
long long u = q.front();
q.pop();
for (long long i : G[u]) {
Edge& e = es[i];
if (!dis[e.to] && e.cap > 0) {
dis[e.to] = dis[u] + 1;
q.push(e.to);
}
}
}
return dis[t];
}
long long dfs(long long u, long long cap) {
if (u == t || cap == 0) return cap;
long long tmp = cap, f;
for (long long& i = cur[u]; i < G[u].size(); i++) {
Edge& e = es[G[u][i]];
if (dis[e.to] == dis[u] + 1) {
f = dfs(e.to, min(cap, e.cap));
e.cap -= f;
es[G[u][i] ^ 1].cap += f;
cap -= f;
if (cap == 0) break;
}
}
return tmp - cap;
}
ll solve() {
ll flow = 0;
while (bfs()) {
cur.assign(n + 1, 0);
flow += dfs(s, INF);
}
return flow;
}
};
int main() {
long long t;
cin>>t;
while(t-->0) {
long long n,m;
cin>>n>>m;
init();
for(long long i=1;i<=m;i++) {
cin>>u[i]>>v[i]>>w[i];
add(u[i],v[i],w[i]);
}
dijkstra(1);
Dinic dinic = Dinic(n,1,n);
for(long long i=1;i<=m;i++) {
if(dis[u[i]]+w[i] == dis[v[i]]){
dinic.addEdge(u[i],v[i],w[i]);
}
}
cout<<dinic.solve()<<endl;
}
return 0;
}