强行二合一最为致命
第一问直接最短路+$DFS$解决
考虑第二问,与深度相关,可以考虑长链剖分。
设$f_{i,j}$表示长度为$i$,经过边数为$j$时的最大边权和,考虑到每一次从重儿子转移过来的时候,不仅要将$f$数组右移一格,还需要同时加上一个值。显然用线段树等数据结构额外维护是不现实的,我们考虑维护一个影响范围为整个$f_i$的加法标记$tag_i$,将$f_{i,0}$设置为$-tag_i$,每一次上传的时候把标记也一起上传,合并轻儿子、计算答案的时候将这个$tag$加上,就能够做到快速地维护了。
长链剖分代码比点分治还长……
1 #include<bits/stdc++.h> 2 #define P pair < int , int > 3 #define int long long 4 //This code is written by Itst 5 using namespace std; 6 7 inline int read(){ 8 int a = 0; 9 bool f = 0; 10 char c = getchar(); 11 while(c != EOF && !isdigit(c)){ 12 if(c == '-') 13 f = 1; 14 c = getchar(); 15 } 16 while(c != EOF && isdigit(c)){ 17 a = (a << 3) + (a << 1) + (c ^ '0'); 18 c = getchar(); 19 } 20 return f ? -a : a; 21 } 22 23 const int MAXN = 30010; 24 vector < P > e[MAXN]; 25 struct edge{ 26 int end , upEd , w; 27 }Ed[MAXN << 1]; 28 int dis[MAXN] , head[MAXN] , dep[MAXN] , len[MAXN] , md[MAXN] , son[MAXN] , f[MAXN << 1] , g[MAXN << 1] , sz[MAXN] , tag[MAXN] , *dp[MAXN] , *cnt[MAXN]; 29 int *p1 = f , *p2 = g , N , M , K , cntEd , ans , times; 30 priority_queue < P > q; 31 bool vis[MAXN]; 32 33 inline void addEd(int a , int b , int c){ 34 Ed[++cntEd].end = b; 35 Ed[cntEd].upEd = head[a]; 36 Ed[cntEd].w = c; 37 head[a] = cntEd; 38 } 39 40 void Dijk(){ 41 q.push(P(0 , 1)); 42 memset(dis , 0x3f , sizeof(dis)); 43 dis[1] = 0; 44 while(!q.empty()){ 45 P t = q.top(); 46 q.pop(); 47 if(-t.first > dis[t.second]) 48 continue; 49 for(int i = 0 ; i < sz[t.second] ; ++i) 50 if(dis[e[t.second][i].first] > dis[t.second] + e[t.second][i].second){ 51 dis[e[t.second][i].first] = dis[t.second] + e[t.second][i].second; 52 q.push(P(-dis[e[t.second][i].first] , e[t.second][i].first)); 53 } 54 } 55 } 56 57 void create(int now){ 58 vis[now] = 1; 59 for(int i = 0 ; i < sz[now] ; ++i) 60 if(!vis[e[now][i].first] && dis[e[now][i].first] == dis[now] + e[now][i].second){ 61 addEd(now , e[now][i].first , e[now][i].second); 62 addEd(e[now][i].first , now , e[now][i].second); 63 create(e[now][i].first); 64 } 65 } 66 67 void dfs1(int now , int pre){ 68 md[now] = dep[now] = dep[pre] + 1; 69 for(int i = head[now] ; i ; i = Ed[i].upEd) 70 if(!dep[Ed[i].end]){ 71 dfs1(Ed[i].end , now); 72 if(md[Ed[i].end] > md[now]){ 73 md[now] = md[Ed[i].end]; 74 son[now] = Ed[i].end; 75 len[now] = Ed[i].w; 76 } 77 } 78 } 79 80 void dfs2(int now){ 81 if(son[now]){ 82 dp[son[now]] = dp[now] + 1; 83 cnt[son[now]] = cnt[now] + 1; 84 dfs2(son[now]); 85 tag[now] = tag[son[now]] + len[now]; 86 dp[now][0] = -tag[now]; 87 } 88 cnt[now][0] = 1; 89 if(ans < dp[now][K] + tag[now]){ 90 ans = dp[now][K] + tag[now]; 91 times = cnt[now][K]; 92 } 93 else 94 if(ans == dp[now][K] + tag[now]) 95 times += cnt[now][K]; 96 for(int i = head[now] ; i ; i = Ed[i].upEd) 97 if(dep[Ed[i].end] == dep[now] + 1 && Ed[i].end != son[now]){ 98 dp[Ed[i].end] = p1; 99 cnt[Ed[i].end] = p2; 100 p1 += (md[Ed[i].end] - dep[Ed[i].end] + 1) << 1; 101 p2 += (md[Ed[i].end] - dep[Ed[i].end] + 1) << 1; 102 dfs2(Ed[i].end); 103 for(int j = 0 ; j <= md[Ed[i].end] - dep[Ed[i].end] && j <= K - 1 ; ++j) 104 if(md[now] - dep[now] >= K - 1 - j) 105 if(ans < tag[Ed[i].end] + dp[Ed[i].end][j] + tag[now] + dp[now][K - 1 - j] + Ed[i].w){ 106 ans = tag[Ed[i].end] + dp[Ed[i].end][j] + tag[now] + dp[now][K - 1 - j] + Ed[i].w; 107 times = cnt[Ed[i].end][j] * cnt[now][K - 1 - j]; 108 } 109 else 110 if(ans == tag[Ed[i].end] + dp[Ed[i].end][j] + tag[now] + dp[now][K - 1 - j] + Ed[i].w) 111 times += cnt[Ed[i].end][j] * cnt[now][K - 1 - j]; 112 for(int j = 1 ; j <= md[Ed[i].end] - dep[Ed[i].end] + 1 && j <= K ; ++j) 113 if(dp[now][j] < dp[Ed[i].end][j - 1] + tag[Ed[i].end] + Ed[i].w - tag[now]){ 114 dp[now][j] = dp[Ed[i].end][j - 1] + tag[Ed[i].end] + Ed[i].w - tag[now]; 115 cnt[now][j] = cnt[Ed[i].end][j - 1]; 116 } 117 else 118 if(dp[now][j] == dp[Ed[i].end][j - 1] + tag[Ed[i].end] + Ed[i].w - tag[now]) 119 cnt[now][j] += cnt[Ed[i].end][j - 1]; 120 } 121 } 122 123 signed main(){ 124 #ifndef ONLINE_JUDGE 125 freopen("2993.in" , "r" , stdin); 126 //freopen("2993.out" , "w" , stdout); 127 #endif 128 N = read(); 129 M = read(); 130 K = read() - 1; 131 for(int i = 1 ; i <= M ; ++i){ 132 int a = read() , b = read() , c = read(); 133 e[a].push_back(P(b , c)); 134 e[b].push_back(P(a , c)); 135 ++sz[a]; 136 ++sz[b]; 137 } 138 for(int i = 1 ; i <= N ; ++i) 139 sort(e[i].begin() , e[i].end()); 140 Dijk(); 141 create(1); 142 dfs1(1 , 0); 143 dp[1] = p1; 144 p1 += md[1] << 1; 145 cnt[1] = p2; 146 p2 += md[1] << 1; 147 dfs2(1); 148 cout << ans << ' ' << times; 149 return 0; 150 }