nowcoder 提高第六場A題
阿新 • • 發佈:2018-11-07
Solution
60分
因為所有的字母要麼全相同要麼全不同, 所以兩條路徑比較字典序只需要比較第一條邊就可以, 於是建反圖, 在反圖上按拓撲序轉移就可以.
因為有環, 所以拓撲完入度還是不為0的點答案為Infinity.
#include <queue> #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> const int N = 1e6 + 7; const long long mod = 998244353; struct Edge { int v, c; Edge* nxt; Edge(int _, int __, Edge* ___) : v(_), c(__), nxt(___) { } }; Edge* head[N]; int du[N]; #define AddEdge(u, v, c) head[u] = new Edge(v, c, head[u]) int vis[N], dis[N], res[N], path[N], len[N]; int main () { int n, m; scanf("%d%d", &n, &m); for (int i = 0; i < m; i += 1) { int u, v, c; scanf("%d%d%d", &u, &v, &c); AddEdge(v, u, c), du[u] += 1; } std:: queue<int> Que; for (int i = 1; i <= n; i += 1) if (not du[i]) Que.push(i), vis[i] = true; while (not Que.empty()) { int u = Que.front(); Que.pop(); for (auto edge = head[u]; edge; edge = edge->nxt) { int v = edge->v, c = edge->c; du[v] -= 1; if (not du[v]) Que.push(v), vis[v] = 1; if (dis[u] + 1 > dis[v]) dis[v] = dis[u] + 1, path[v] = u, len[v] = c, res[v] = (res[u] * 29ll % mod + c * 29ll % mod) % mod; if (dis[u] + 1 == dis[v] and c < len[v]) path[v] = u, len[v] = c, res[v] = (res[u] * 29ll % mod + c * 29ll % mod) % mod; } } for (int i = 1; i <= n; i += 1) vis[i] ? printf("%d\n", res[i]) : printf("Infinity\n"); return 0; }
100分-倍增
剩下的40分難點在於比較路徑字典序的大小.
如何找出兩條路徑第一個不同的位置?
可以用倍增, 具體就是預處理出點u
向後走\(1\)個位置路徑的hash值, 向後走\(2\)個位置路徑的hash值, 向後走\(2^k\)個位置路徑的hash值.
考試的時候真的是沒有想到呀.