题目
解题思路
这是一道简单的二合一题。
首先,题目说只能走最短路径。我们先求出1到所有点的最短路径,依此判断每条边是否是松弛边。
其次,处理器有处理上限。我们将处理器拆成入端和出端,入端向出端连容量为处理能力的边,所有松弛边权值算无穷。对这个图跑最大流即可。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
#define MP make_pair
typedef long long ll;
const int N = 2e5 + 100;
const ll INF = 1e16;
vector<pair<int, int> > V[N];
int dis[N];
bool inque[N];
void spfa(int s) {
memset(dis, 0x3f3f3f3f, sizeof(dis));
dis[s] = 0;
queue<int> Q;
Q.push(s);
while (!Q.empty()) {
int u = Q.front();
Q.pop(); inque[u] = false;
for (auto x : V[u]) {
int v = x.first, c = x.second;
if (dis[v] > dis[u] + c) {
dis[v] = dis[u] + c;
if (!inque[v]) {
Q.push(v);
inque[v] = true;
}
}
}
}
}
struct node {
ll to, cap, rev;
node() {}
node(ll to, ll cap, ll rev):to(to), cap(cap), rev(rev) {}
};
vector<node> G[N];
int iter[N], level[N];
void addedge(int from, int to, ll cap) {
G[from].push_back(node(to, cap, G[to].size()));
G[to].push_back(node(from, 0, G[from].size() - 1));
}
void bfs(int s) {
memset(level, -1, sizeof(level));
queue<int> Q;
level[s] = 0;
Q.push(s);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
for (node e : G[u]) {
if (e.cap > 0 && level[e.to] < 0) {
level[e.to] = level[u] + 1;
Q.push(e.to);
}
}
}
}
ll dfs(int s, int t, ll f) {
if (s == t) return f;
for (int &i = iter[s]; i < G[s].size(); i++) {
node &e = G[s][i];
if (e.cap > 0 && level[s] < level[e.to]) {
ll d = dfs(e.to, t, min(f, e.cap));
if (d > 0) {
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
return 0;
}
ll maxflow(int s, int t) {
ll ans = 0, f;
while (true) {
bfs(s);
if (level[t] < 0) return ans;
memset(iter, 0, sizeof(iter));
while ((f = dfs(s, t, INF)) > 0)
ans += f;
}
}
int n, m, s, t;
int aa[N], bb[N], cc[N];
int main() {
//freopen("0.txt", "r", stdin);
ll a, b, c;
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
scanf("%lld%lld%lld", &aa[i], &bb[i], &cc[i]);
V[aa[i]].push_back(MP(bb[i], cc[i]));
V[bb[i]].push_back(MP(aa[i], cc[i]));
}
spfa(1);
for (int i = 1; i <= m; i++) {
if (dis[aa[i]] > dis[bb[i]]) swap(aa[i], bb[i]);
if (dis[aa[i]] + cc[i] == dis[bb[i]]) {
addedge(aa[i] * 2 + 1, bb[i] * 2, INF);
}
}
for (int i = 1; i <= n; i++) {
scanf("%lld", &a);
addedge(i * 2, i * 2 + 1, a);
}
printf("%lld\n", maxflow(3, n * 2));
return 0;
}