
因为C是不断变化的而且C是和点权相关和边权无关 所以我们可以MCMF但是MCMF的时候不能与C相关
再分析问题 我们可以认为每条路径S->T只覆盖T这个终点 因为题目中说了如果Si != Ti 要多付出 C的代价
假设我们走过的路径形成了一个环则刚好 边数=点数 覆盖完了
如果走过的路径不是一个环 则还有起点没有覆盖 此时我们可以把它当作没有途径的城市 给他补偿 同样为C
所以我们把原图拆成左边出点 右边入点 传递闭包后建图
这样每次MCMF增广的代价是不递减的 并且每增广一次多覆盖一个点 所以我们把每次增广的代价放到一个数组里面
每次询问我们二分C在数组里的位置,在C之前的点我们利用路径覆盖 在C及C之后的点我们用C去补偿它
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAX 255
inline int read() {
int x = 0;
bool t = false;
char ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-')
ch = getchar();
if (ch == '-')
t = true, ch = getchar();
while (ch <= '9' && ch >= '0')
x = x * 10 + ch - 48, ch = getchar();
return t ? -x : x;
}
int val[MAX], sum[MAX], tot;
namespace MCMF {
const int MAXM = 1000000, MAXN = 1000;
struct Line {
int v, next, w, fy;
} e[MAXM];
int h[MAXN], cnt = 2;
inline void Add(int u, int v, int w, int fy) {
e[cnt] = (Line) {
v, h[u], w, fy
};
h[u] = cnt++;
e[cnt] = (Line) {
u, h[v], 0, -fy
};
h[v] = cnt++;
}
int dis[MAXN], pe[MAXN], pv[MAXN], Cost, Flow;
bool vis[MAXN];
queue<int> Q;
int S = 0, T = MAXN - 1;
bool SPFA() {
memset(dis, 63, sizeof(dis));
dis[S] = 0;
Q.push(S);
vis[S] = true;
while (!Q.empty()) {
int u = Q.front();
Q.pop();
for (int i = h[u]; i; i = e[i].next) {
int v = e[i].v;
if (!e[i].w)
continue;
if (dis[u] + e[i].fy < dis[v]) {
dis[v] = dis[u] + e[i].fy;
pe[v] = i, pv[v] = u;
if (!vis[v])
vis[v] = true, Q.push(v);
}
}
vis[u] = false;
}
if (dis[T] >= 1e9)
return false;
int flow = 1e9;
for (int i = T; i != S; i = pv[i])
flow = min(flow, e[pe[i]].w);
for (int i = T; i != S; i = pv[i])
e[pe[i]].w -= flow, e[pe[i] ^ 1].w += flow;
Flow += flow;
Cost += dis[T] * flow;
val[++tot] = dis[T] * flow;
sum[tot] = sum[tot - 1] + val[tot];
return true;
}
}
using namespace MCMF;
int n, m, q, g[MAX][MAX];
int main() {
n = read();
m = read();
q = read();
memset(g, 63, sizeof(g));
for (int i = 1; i <= n; ++i)
g[i][i] = 0;
for (int i = 1, u, v; i <= m; ++i)
u = read(), v = read(), g[u][v] = min(read(), g[u][v]);
for (int k = 1; k <= n; ++k)
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
if (i ^ j)
Add(i, j + n, 1, g[i][j]);
for (int i = 1; i <= n; ++i)
Add(S, i, 1, 0), Add(i + n, T, 1, 0);
while (SPFA());
while (q--) {
int C = read(), l = 1, r = tot, ret = 0;
while (l <= r) {
int mid = (l + r) >> 1;
if (val[mid] < C)
l = mid + 1, ret = mid;
else
r = mid - 1;
}
printf("%d\n", sum[ret] + (n - ret)*C);
}
return 0;
}