本题算法:最短路树
这是个啥玩意呢,就是对于一个图,构造一棵树,使从源点开始的单源最短路径与原图一模一样。怎么做呢,跑一边Dijkstra,然后对于一个点u,枚举它的边,设当前的边为cur_edge,如果dis[u]+cue_edge的长度=dis[cur_edge的终点],那么显然这条边应该珂以是最短路树上的一条边,然后打一个标记表示cur_edge的终点不能再被加边了,题目要求字典序最小,显然u从1到n枚举珂以解决问题。
建好树以后跑一边DFS,我们知道当前节点u上连边的贡献是((dis[u] - t) imes)以(u)为根的子树的牛的个数,找到贡献最大的点更新答案即可。
代码:
#include <cstdio>
#include <queue>
#include <algorithm>
#include <set>
#include <map>
#define ll long long
using namespace std;
ll read(){
ll x = 0; int zf = 1; char ch = ' ';
while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
if (ch == '-') zf = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
}
struct Edge{
int from, to, next; ll dis;
} edges[1000001];
int head[300001], edge_num = 0;
ll dis[300001];
inline void addEdge(int u, int v, ll w){
edges[++edge_num] = (Edge){u, v, head[u], w};
head[u] = edge_num;
}
set< pair<ll, int> > que;
int n, t, s = 1;
void dijkstra(){
for (int i = 1; i <= n; ++i)
dis[i] = (1ll << 62);
dis[s] = 0; que.insert(make_pair(0, s));
pair<ll, int> uu; int u, v;
while (!que.empty()){
uu = *que.begin(); que.erase(uu);
u = uu.second;
for (int c_e = head[u]; c_e; c_e = edges[c_e].next){
v = edges[c_e].to;
if (dis[u] + edges[c_e].dis < dis[v]){
que.erase(make_pair(dis[v], v));
dis[v] = dis[u] + edges[c_e].dis;
que.insert(make_pair(dis[v], v));
}
}
}
}
vector<int> vec[100001];
ll ans = 0;
int a[100001];
int vis[100001];
int DFS(int u){
int v, cnt = 0; vis[u] = 1;
for (int i = 0; i < vec[u].size(); ++i){
v = vec[u][i];
if (!vis[v])
cnt += DFS(v);
}
cnt += a[u];
ans = max(ans, (dis[u] - t) * cnt);
return cnt;
}
int v2[100001];
signed main(){
int m; n = read(), m = read(), t = read();
for (int i = 1; i <= n; ++i) a[i] = read();
int u, v; ll w;
for (int i = 1; i <= m; ++i){
u = read(), v = read(), w = read();
addEdge(u, v, w), addEdge(v, u, w);
}
dijkstra();
for(int i = 1; i <= n; ++i)
for(int c_e = head[i]; c_e; c_e = edges[c_e].next)
if(dis[edges[c_e].to] == dis[i] + edges[c_e].dis && !v2[edges[c_e].to]){
v2[edges[c_e].to] = 1;
vec[i].push_back(edges[c_e].to), vec[edges[c_e].to].push_back(i);
}
DFS(1);
printf("%lld", ans);
return 0;
}