题目大意:略 传送门
硬是把两个题拼到了一起= =
$dijkstra$搜出单源最短路,然后$dfs$建树,如果$dis_{v}=dis_{u}+e.val$,说明这条边在最短路图内,然后像$NOIP2018 D2T1$那样的思路,贪心地选出当前节点的所有子节点里,未被访问过的编号最小的节点递归,回溯后重复此过程。可以用$vector$预处理出来,或者用堆= =。
然后就是很经典的点分治问题了
求出树上固定边数的最长链,类似于[IOI2011]Race这道题的思路,只不过是反着搞。每次选择一个重心为根,开个桶统计答案就行了
求固定长度链的个数。但这道题用桶可能会存不下,可以写$map$代替桶(不过数据里好像没有存不下的情况..)。
由于判定条件是二元的,一个是边数一个是长度,排序双指针不知道行不行
还有我把$vector$改成堆就过了是什么鬼
代码巨长巨恶心
1 #include <map> 2 #include <queue> 3 #include <vector> 4 #include <cstdio> 5 #include <cstring> 6 #include <algorithm> 7 #define N1 30010 8 #define M1 1010 9 #define ll long long 10 #define inf 233333333 11 #define it map<node,int>::iterator 12 using namespace std; 13 14 int gint() 15 { 16 int ret=0,fh=1;char c=getchar(); 17 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 18 while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} 19 return ret*fh; 20 } 21 int n,m,K; 22 struct Edge{ 23 int to[N1<<2],nxt[N1<<2],val[N1<<2],head[N1],cte; 24 void ae(int u,int v,int w) 25 { 26 cte++;to[cte]=v,val[cte]=w; 27 nxt[cte]=head[u],head[u]=cte; 28 } 29 }g,e; 30 namespace Build_Tree{ 31 struct node{ 32 int id,val; 33 friend bool operator < (const node &s1,const node &s2){ 34 if(s1.val!=s2.val) return s1.val>s2.val; 35 return s1.id>s2.id; 36 } 37 }; 38 int cmp(node s1,node s2){return s1.id<s2.id;} 39 int vis[N1],dis[N1]; 40 void dijkstra() 41 { 42 memset(dis,0x3f,sizeof(dis)); 43 priority_queue<node>q; 44 q.push((node){1,0}); dis[1]=0; 45 int j,u,v; node k; 46 while(!q.empty()) 47 { 48 k=q.top(); q.pop(); u=k.id; if(vis[u]) continue; vis[u]=1; 49 for(j=g.head[u];j;j=g.nxt[j]) 50 { 51 v=g.to[j]; 52 if(dis[v]>dis[u]+g.val[j]) 53 dis[v]=dis[u]+g.val[j], q.push((node){v,dis[v]}); 54 } 55 } 56 memset(vis,0,sizeof(vis)); 57 } 58 priority_queue<node>q[N1]; 59 void dfs(int u) 60 { 61 vis[u]=1; node k; 62 for(int j=g.head[u];j;j=g.nxt[j]) 63 { 64 if(vis[g.to[j]]||dis[g.to[j]]!=dis[u]+g.val[j]) continue; 65 q[u].push((node){g.val[j],g.to[j]}); 66 } 67 while(!q[u].empty()) 68 { 69 k=q[u].top(); q[u].pop(); if(vis[k.val]) continue; 70 e.ae(u,k.val,k.id); e.ae(k.val,u,k.id); 71 dfs(k.val); 72 } 73 } 74 void Main() 75 { 76 dijkstra(); 77 dfs(1); 78 } 79 }; 80 int sz[N1],ms[N1],use[N1],tsz,G; 81 void gra(int u,int dad) 82 { 83 sz[u]=1; ms[u]=0; 84 for(int j=e.head[u];j;j=e.nxt[j]) 85 { 86 if(use[e.to[j]]||e.to[j]==dad) continue; 87 gra(e.to[j],u); 88 sz[u]+=sz[e.to[j]]; ms[u]=max(ms[u],sz[e.to[j]]); 89 } 90 ms[u]=max(ms[u],tsz-sz[u]); 91 if(ms[u]<ms[G]) G=u; 92 } 93 94 int ma[N1],q[N1],eq,tq[N1],et,dep[N1],dis[N1]; 95 96 namespace Find_ma{ 97 int ans; 98 void dfs(int u,int dad) 99 { 100 if(dep[u]>K) return; tq[++et]=u; 101 for(int j=e.head[u];j;j=e.nxt[j]) 102 { 103 if(use[e.to[j]]||e.to[j]==dad) continue; 104 dep[e.to[j]]=dep[u]+1; dis[e.to[j]]=dis[u]+e.val[j]; 105 dfs(e.to[j],u); 106 } 107 } 108 void calc(int u) 109 { 110 int i,j,x; 111 dep[u]=0; ma[0]=0; 112 for(j=e.head[u];j;j=e.nxt[j]) 113 { 114 if(use[e.to[j]]) continue; 115 dep[e.to[j]]=1; dis[e.to[j]]=e.val[j]; 116 dfs(e.to[j],u); 117 for(i=1;i<=et;i++) 118 { 119 x=tq[i]; 120 ans=max(ans,ma[K-dep[x]]+dis[x]); 121 } 122 while(et) 123 { 124 x=tq[et--]; q[++eq]=dep[x]; 125 ma[dep[x]]=max(ma[dep[x]],dis[x]); 126 } 127 } 128 while(eq) ma[q[eq--]]=-inf; 129 } 130 void main_dfs(int u) 131 { 132 int j,v; use[u]=1; calc(u); 133 for(j=e.head[u];j;j=e.nxt[j]) 134 { 135 v=e.to[j]; if(use[v]) continue; 136 tsz=sz[v]; G=0; gra(v,u); 137 main_dfs(G); 138 } 139 } 140 void solve() 141 { 142 ms[0]=tsz=n; G=0; gra(1,-1); gra(G,-1); 143 for(int i=1;i<=n;i++) ma[i]=-inf; 144 main_dfs(G); 145 } 146 }; 147 148 namespace Count{ 149 150 struct node{ 151 int dis,dep; 152 friend bool operator < (const node &s1,const node &s2) 153 { 154 if(s1.dis!=s2.dis) return s1.dis<s2.dis; 155 return s1.dep<s2.dep; 156 } 157 }; 158 int M,ans; map<node,int>mp; 159 void dfs(int u,int dad) 160 { 161 if(dis[u]>M||dep[u]>K) return; 162 mp[(node){dis[u],dep[u]}]++; 163 for(int j=e.head[u];j;j=e.nxt[j]) 164 { 165 if(use[e.to[j]]||e.to[j]==dad) continue; 166 dep[e.to[j]]=dep[u]+1; dis[e.to[j]]=dis[u]+e.val[j]; 167 dfs(e.to[j],u); 168 } 169 } 170 int calc(int u) 171 { 172 int ret=0; node k,t; mp.clear(); dfs(u,-1); 173 for(it i=mp.begin();i!=mp.end();i++) 174 { 175 k=i->first; t=(node){M-k.dis,K-k.dep}; 176 if(mp.find(t)==mp.end()) continue; 177 if(k.dis==t.dis&&k.dep==t.dep) ret+=(i->second)*((i->second)-1); 178 else ret+=mp[t]*(i->second); 179 } 180 return ret/2; 181 } 182 void main_dfs(int u) 183 { 184 int j,v; use[u]=1; dis[u]=0; dep[u]=0; ans+=calc(u); 185 for(j=e.head[u];j;j=e.nxt[j]) 186 { 187 v=e.to[j]; if(use[v]) continue; 188 ans-=calc(v); tsz=sz[v]; G=0; gra(v,u); 189 main_dfs(G); 190 } 191 } 192 void solve() 193 { 194 M=Find_ma::ans; 195 memset(use,0,sizeof(use)); 196 ms[0]=tsz=n; G=0; gra(1,-1); gra(G,-1); 197 main_dfs(G); 198 } 199 }; 200 201 int main() 202 { 203 //freopen("t2.in","r",stdin); 204 int i,x,y,z; 205 scanf("%d%d%d",&n,&m,&K); K--; 206 for(i=1;i<=m;i++) 207 { 208 x=gint(),y=gint(),z=gint(); 209 g.ae(x,y,z),g.ae(y,x,z); 210 } 211 Build_Tree::Main(); 212 Find_ma::solve(); 213 Count::solve(); 214 printf("%d %d ",Find_ma::ans,Count::ans); 215 return 0; 216 } 217 /* 218 6 6 4 219 1 2 1 220 2 3 1 221 3 4 1 222 2 5 1 223 3 6 1 224 5 6 1 225 226 3 4 227 228 7 6 4 229 1 2 2 230 1 3 1 231 2 4 4 232 2 5 3 233 3 6 2 234 5 7 2 235 236 9 1 237 */