bzoj 4016: [FJOI2014]最短路径树问题 最短路+点分治
来源:互联网 发布:唐安琪最新知乎 编辑:程序博客网 时间:2024/06/05 19:09
题意
给一个包含n个点,m条边的无向连通图。从顶点1出发,往其余所有点分别走一次并返回。
往某一个点走时,选择总长度最短的路径走。若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径(如路径A为1,32,11,路径B为1,3,2,11,路径B字典序较小。注意是序列的字典序的最小,而非路径中节点编号相连的字符串字典序最小)。到达该点后按原路返回,然后往其他点走,直到所有点都走过。
可以知道,经过的边会构成一棵最短路径树。请问,在这棵最短路径树上,最长的包含K个点的简单路径长度为多长?长度为该最长长度的不同路径有多少条?
这里的简单路径是指:对于一个点最多只经过一次的路径。不同路径是指路径两端端点至少有一个不同,点A到点B的路径和点B到点A视为同一条路径。
n<=30000,m<=60000,2<=K<=n。
分析
首先要把最短路树求出来。这个的话可以先把原图的最短路DAG求出来,然后从1开始,每次沿着字典序最小的边跑,就可以得到最短路树。
那后就是个sb点分治了。
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int N=30005;const int inf=1000000000;int n,m,k,cnt,last[N],tot,ans,ans1,dis[N],now,t[N],size[N],mx[N],root,s[N];bool vis[N];pair<int,int> a[N];pair<int,pair<int,int> > tmp[N*2];struct edge{int to,next,w,use;}e[N*4];priority_queue<pair<int,int> > que;int read(){ int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}void addedge(int u,int v,int w){ e[++cnt].to=v;e[cnt].w=w;e[cnt].next=last[u];last[u]=cnt; e[++cnt].to=u;e[cnt].w=w;e[cnt].next=last[v];last[v]=cnt;}void dfs(int x){ vis[x]=1; for (int i=last[x];i;i=e[i].next) if (e[i].use==1&&!vis[e[i].to]) e[i].use=e[i^1].use=2,dfs(e[i].to);}void dij(){ for (int i=2;i<=n;i++) dis[i]=inf; que.push(make_pair(0,1)); while (!que.empty()) { pair<int,int> u=que.top();que.pop(); while (!que.empty()&&vis[u.second]) u=que.top(),que.pop(); if (vis[u.second]) break; int x=u.second;vis[x]=1; for (int i=last[x];i;i=e[i].next) if (!vis[e[i].to]&&dis[x]+e[i].w<dis[e[i].to]) { dis[e[i].to]=dis[x]+e[i].w; que.push(make_pair(-dis[e[i].to],e[i].to)); } } for (int i=2;i<=cnt;i++) { int x=e[i^1].to,y=e[i].to; if (dis[x]+e[i].w==dis[y]) e[i].use=1; } memset(vis,0,sizeof(vis)); dfs(1);}void get_root(int x,int fa){ size[x]=1;mx[x]=0; for (int i=last[x];i;i=e[i].next) { if (e[i].use<2||vis[e[i].to]||e[i].to==fa) continue; get_root(e[i].to,x); size[x]+=size[e[i].to]; mx[x]=max(mx[x],size[e[i].to]); } mx[x]=max(mx[x],tot-size[x]); if (!root||mx[x]<mx[root]) root=x;}void get_w(int x,int len,int dis,int fa){ if (len<=k) a[++now]=make_pair(dis,len); size[x]=1; for (int i=last[x];i;i=e[i].next) { if (e[i].use<2||vis[e[i].to]||e[i].to==fa) continue; get_w(e[i].to,len+1,dis+e[i].w,x); size[x]+=size[e[i].to]; }}void solve(int x){ vis[x]=1; now=0; for (int i=last[x];i;i=e[i].next) { if (e[i].use<2||vis[e[i].to]) continue; int tmp=now; get_w(e[i].to,1,e[i].w,x); for (int j=tmp+1;j<=now;j++) { int w=a[j].first,len=a[j].second; if (t[k-len]>-1) { if (w+t[k-len]>ans) ans=w+t[k-len],ans1=s[k-len]; else if (w+t[k-len]==ans) ans1+=s[k-len]; } } for (int j=tmp+1;j<=now;j++) { int w=a[j].first,len=a[j].second; if (w>t[len]) t[len]=w,s[len]=1; else if (w==t[len]) s[len]++; } } while (now) t[a[now].second]=-1,s[a[now].second]=0,now--; for (int i=last[x];i;i=e[i].next) { if (e[i].use<2||vis[e[i].to]) continue; root=0;tot=size[e[i].to]; get_root(e[i].to,x); solve(root); }}int main(){ n=read();m=read();k=read()-1;cnt=1; for (int i=1;i<=m;i++) { int x=read(),y=read(),z=read(); tmp[i]=make_pair(x,make_pair(y,z)); } sort(tmp+1,tmp+m+1); for (int i=m;i>=1;i--) addedge(tmp[i].first,tmp[i].second.first,tmp[i].second.second); dij(); memset(vis,0,sizeof(vis)); tot=n;root=0; get_root(1,0); for (int i=1;i<=k;i++) t[i]=-1; s[0]=1; solve(root); printf("%d %d",ans,ans1); return 0;}
阅读全文
0 0
- bzoj 4016: [FJOI2014]最短路径树问题 最短路+点分治
- 4016: [FJOI2014]最短路径树问题 点分治
- 【bzoj 4016】[FJOI2014]最短路径树问题 树分治+树形dp
- 【BZOJ 4016】[FJOI2014]最短路径树问题
- bzoj 4016: [FJOI2014]最短路径树问题
- BZOJ 4016: [FJOI2014]最短路径树问题
- 4016: [FJOI2014]最短路径树问题
- 4016: [FJOI2014]最短路径树问题
- 【树的分治】FJOI2014最短路径树问题
- 【BZOJ4016】最短路径树问题,最短路+点分治
- 【BZOJ4016】【FJOI2014】 最短路径树问题 树的点分治
- BZOJ 4016 最短路径树问题 [最短路+树分治]
- BZOJ4016: [FJOI2014]最短路径树问题
- FJOI2014最短路径树问题
- 【FJOI2014[bzoj4016]】最短路径树问题
- BZOJ4016: [FJOI2014]最短路径树问题
- [FJOI2014]最短路径树问题
- BZOJ4016 最短路径树问题(点分治)
- FPGA设计之时序约束
- JavaScript基本知识
- 0基础入门,写的第一个浮动元素代码
- 拖拽效果的实现
- 1022. Digital Library (30)
- bzoj 4016: [FJOI2014]最短路径树问题 最短路+点分治
- Unity AI 群组行为
- 洛谷 P3178 [HAOI2015]树上操作
- zk实现分布式锁
- 决策树算法之ID3
- OpenGL+Qt界面(三) Qt中实现OPENGL的基本交互+代码
- linux debuginfo 文件操作
- (二)spring的注入---配置构造器属性注入
- Java学习博客汇总