简单题。
题意:给出一张图,边权为 \(1\),每个点有属性 \(a,b\),定义一个点 \(u\) 的权值 \(f(u)\) 为 \(\max _{u\not=v}a_v-b_v\operatorname{dis}(u,v)\),按从小到大的顺序输出与 \(1\) 相连的的点的 \(f\) 值。
做法:
首先观察到只需要输出与 \(1\) 相连的而不是任一点,说明这是有意义的。我们注意到,与 \(1\) 相连的点 \(u\),与其他 \(v\) 的距离 \(\operatorname{dis}(u,v)\) 和 \(\operatorname{dis}(1,v)\) 相差不会超过 \(1\),所以可以直接讨论三者的贡献。
首先对于 \(\operatorname{dis}(1,v)+1\),因为这个是最差的可能,直接全部更新就可以了。
然后对于 \(\operatorname{dis}(1,v) - 1\) 和 \(\operatorname{dis}(1,v)\),前者等于,我令 \(\operatorname{dis}(1,x)+1=\operatorname{dis}(1,y)\) 的这些边在新图上连一条 \(x\rightarrow y\) 的有向边,然后只能走这些有向边到达;后者等于我可以走一条 \(\operatorname{dis}(1,x)=\operatorname{dis}(1,y)\) 的边。
第一种边很好连,关键在于第二种我只能走一条,只能走一条这种限制很分层图,直接拆开就可以了。
记得要求 \(u\not=v\)。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 6e5 + 5;
int n, m, a[maxn], b[maxn], ans[maxn];
vector<int> e[maxn], g[maxn];
int dis[maxn];
void bfs(int s) {memset(dis, 0x3f, sizeof(dis));dis[s] = 0;queue<int> q; q.push(s);while(!q.empty()) {int u = q.front(); q.pop();for (int i = 0; i < e[u].size(); i++) {int v = e[u][i];if(dis[v] > dis[u] + 1) {dis[v] = dis[u] + 1;q.push(v);}}}
}
int vis[maxn], res[maxn];
struct node {int val, p;friend bool operator<(node x, node y) {return (x.val < y.val ? 1 : 0);}node() {val = -9e18, p = 0;}node(int V, int P) {val = V, p = P;}
} mx, smx;void dfs(int u) {if(vis[u])return ;vis[u] = 1;res[u] = a[u] - b[u] * dis[u];for (int i = 0; i < g[u].size(); i++) {int v = g[u][i];dfs(v);ans[u] = max(ans[u], res[v]);}res[u] = max(res[u], ans[u]);
// cout << u << " " << ans[u] << " " << res[u] << endl;
}
signed main() {cin >> n >> m;for (int i = 1; i <= n; i++)cin >> a[i] >> b[i];for (int i = 1; i <= m; i++) {int x, y; cin >> x >> y;e[x].push_back(y);e[y].push_back(x);}bfs(1);memset(ans, -0x3f, sizeof(ans));for (int i = 1; i <= n; i++) {node t = node{a[i] - (dis[i] + 1) * b[i], i};if(smx < t)smx = t;if(mx < smx)swap(smx, mx);}
// cout << mx.val << " " << mx.p << endl;for (int i = 1; i <= n; i++) {for (int j = 0; j < e[i].size(); j++) {int k = e[i][j];if(dis[i] + 1 == dis[k])g[i].push_back(k), g[i + n].push_back(n + k);else if(dis[i] == dis[k])g[i].push_back(k + n);}}for (int i = 1; i <= n; i++)dis[i + n] = dis[i], dis[i] = max(dis[i] - 1, 0ll),a[i + n] = a[i], b[i + n] = b[i];for (int i = 1; i <= 2 * n; i++)dfs(i);sort(e[1].begin(), e[1].end());for (int i = 0; i < e[1].size(); i++) {if(e[1][i] == mx.p)cout << max(smx.val, ans[e[1][i]]) << endl;elsecout << max(mx.val, ans[e[1][i]]) << endl;}return 0;
}
/*
3 3
1235 123
2152 242
324 31
1 2
2 3
3 1
*/