BZOJ 4016: [FJOI2014]最短路径树问题
建最短路树的时候,优先队列加一条限制,当花费相同的时候id小的排前面
这样建出来的最短路树就是符合题意的
再考虑点分治
因为不满足前缀加减性,那么考虑按序遍历即可
考虑如何同时维护最大值及其个数
判断当前值是大于还是等于已经存的值
如果大于 替换掉,次数置为1
如果等于 次数++
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define INF 0x3f3f3f3f 5 #define N 60010 6 #define pii pair <int, int> 7 int n, m, k; 8 struct Graph 9 { 10 struct node 11 { 12 int to, nx, w; 13 node() {} 14 node(int to, int nx, int w) : to(to), nx(nx), w(w) {} 15 }a[N << 1]; 16 int head[N], pos; 17 void init() 18 { 19 memset(head, 0, sizeof head); 20 pos = 0; 21 } 22 void add(int u, int v, int w) 23 { 24 a[++pos] = node(v, head[u], w); head[u] = pos; 25 a[++pos] = node(u, head[v], w); head[v] = pos; 26 } 27 }G[2]; 28 #define erp(G, u) for (int it = G.head[u], v = G.a[it].to, w = G.a[it].w; it; it = G.a[it].nx, v = G.a[it].to, w = G.a[it].w) 29 30 struct node 31 { 32 int u, w, fa, v; 33 node() {} 34 node(int u, int w, int fa, int v) : u(u), w(w), fa(fa), v(v) {} 35 bool operator < (const node &other) const 36 { 37 if (w != other.w) return w > other.w; 38 return u > other.u; 39 } 40 }; 41 int dist[N], used[N]; 42 void Dijkstra() 43 { 44 for (int i = 1; i <= n; ++i) dist[i] = INF, used[i] = false; 45 dist[1] = 0; priority_queue <node> q; q.push(node(1, 0, -1, 0)); 46 while (!q.empty()) 47 { 48 int u = q.top().u; 49 if (used[u]) 50 { 51 q.pop(); 52 continue; 53 } 54 if (u != 1) 55 G[1].add(q.top().fa, u, q.top().v); 56 q.pop(); 57 used[u] = true; 58 erp(G[0], u) if (!used[v] && dist[v] > dist[u] + w) 59 { 60 dist[v] = dist[u] + w; 61 q.push(node(v, dist[v], u, w)); 62 } 63 } 64 } 65 66 int vis[N]; 67 int sum, root, sze[N], f[N]; 68 void getroot(int u, int fa) 69 { 70 f[u] = 0, sze[u] = 1; 71 erp(G[1], u) if (v != fa && !vis[v]) 72 { 73 getroot(v, u); 74 sze[u] += sze[v]; 75 f[u] = max(f[u], sze[v]); 76 } 77 f[u] = max(f[u], sum - sze[u]); 78 if (f[u] < f[root]) root = u; 79 } 80 81 int deep[N], res[2]; pii t[N]; 82 void getdeep(int u, int fa) 83 { 84 if (deep[u] <= k) 85 { 86 int tmp = dist[u] + t[k - deep[u] + 1].first; 87 if (tmp == res[0]) res[1] += t[k - deep[u] + 1].second; 88 else if (tmp > res[0]) res[0] = tmp, res[1] = 1; 89 } 90 erp(G[1], u) if (v != fa && !vis[v]) 91 { 92 deep[v] = deep[u] + 1; 93 dist[v] = dist[u] + w; 94 getdeep(v, u); 95 } 96 } 97 98 void add(int u, int fa, int flag) 99 { 100 if (deep[u] <= k) 101 { 102 if (flag) 103 { 104 if (dist[u] == t[deep[u]].first) ++t[deep[u]].second; 105 else if (dist[u] > t[deep[u]].first) t[deep[u]] = pii(dist[u], 1); 106 } 107 else t[deep[u]] = pii(0, 0); 108 } 109 erp(G[1], u) if (v != fa && !vis[v]) 110 add(v, u, flag); 111 } 112 113 void solve(int u) 114 { 115 vis[u] = 1; 116 t[1] = pii(0, 1); 117 erp(G[1], u) if (!vis[v]) 118 { 119 deep[v] = 2, dist[v] = w; 120 getdeep(v, u); add(v, u, 1); 121 } 122 erp(G[1], u) if (!vis[v]) 123 add(v, u, 0); 124 erp(G[1], u) if (!vis[v]) 125 { 126 sum = f[0] = sze[v]; root = 0; 127 getroot(v, 0); 128 solve(root); 129 } 130 } 131 132 void Run() 133 { 134 while (scanf("%d%d%d", &n, &m, &k) != EOF) 135 { 136 G[0].init(); G[1].init(); 137 memset(res, 0, sizeof res); 138 memset(vis, 0, sizeof vis); 139 for (int i = 1, u, v, w; i <= m; ++i) 140 { 141 scanf("%d%d%d", &u, &v, &w); 142 G[0].add(u, v, w); 143 } 144 Dijkstra(); 145 sum = f[0] = n; root = 0; 146 getroot(1, 0); 147 solve(root); 148 printf("%d %d\n", res[0], res[1]); 149 } 150 } 151 152 int main() 153 { 154 #ifdef LOCAL 155 freopen("Test.in", "r", stdin); 156 #endif 157 158 Run(); 159 return 0; 160 }