bzoj 4016: [FJOI2014]最短路径树问题
来源:互联网 发布:js获取cookie过期时间 编辑:程序博客网 时间:2024/05/18 03:34
4016: [FJOI2014]最短路径树问题
Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 1025 Solved: 359
[Submit][Status][Discuss]
Description
给一个包含n个点,m条边的无向连通图。从顶点1出发,往其余所有点分别走一次并返回。
往某一个点走时,选择总长度最短的路径走。若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径(如路径A为1,32,11,路径B为1,3,2,11,路径B字典序较小。注意是序列的字典序的最小,而非路径中节点编号相连的字符串字典序最小)。到达该点后按原路返回,然后往其他点走,直到所有点都走过。
可以知道,经过的边会构成一棵最短路径树。请问,在这棵最短路径树上,最长的包含K个点的简单路径长度为多长?长度为该最长长度的不同路径有多少条?
这里的简单路径是指:对于一个点最多只经过一次的路径。不同路径是指路径两端端点至少有一个不同,点A到点B的路径和点B到点A视为同一条路径。
Input
第一行输入三个正整数n,m,K,表示有n个点m条边,要求的路径需要经过K个点。接下来输入m行,每行三个正整数Ai,Bi,Ci(1<=Ai,Bi<=n,1<=Ci<=10000),表示Ai和Bi间有一条长度为Ci的边。数据保证输入的是连通的无向图。
Output
输出一行两个整数,以一个空格隔开,第一个整数表示包含K个点的路径最长为多长,第二个整数表示这样的不同的最长路径有多少条。
Sample Input
6 6 4
1 2 1
2 3 1
3 4 1
2 5 1
3 6 1
5 6 1
1 2 1
2 3 1
3 4 1
2 5 1
3 6 1
5 6 1
Sample Output
3 4
HINT
对于所有数据n<=30000,m<=60000,2<=K<=n。
数据保证最短路径树上至少存在一条长度为K的路径。
2016.12.7新加数据一组by - wyx-150137
mdzz刷的这几道题就这道最水(相对),虽然代码也不短,但是套路呀
点分套路题,具体点分套路请见:普通套路 和 一般套路
若想拓展点分树套路请见:点分树套路
好了我们开始题解:
一共两问:
长度为k的最长路径 和 长度为k的权值长为最长权值的路径条数
千万要读清第二问!!!
第二问也要求长度为k!!!
以开始以为第二问不限制长度,以为这题两问两个套路,实际上都是不满足前缀减法的 一般套路
辣么熟悉点分治套路的同学就可以随便切了,不熟悉的建议先切上面普通套路 和一般套路这两道题
代码:
/************************************************************** Problem: 4016 User: ********** Language: C++ Result: Accepted Time:944 ms Memory:29716 kb****************************************************************/ #include<iostream>#include<algorithm>#include<cstring>#include<string>#include<cstdlib>#include<cmath>#include<cstdio>#include<climits>#include<queue>#include<stack>#include<map>#include<set>#define N 100010#define M 200020#define inf 1<<26#define pa pair<int,int>#define lowbit(x) x&(-x)using namespace std;int read(){ int x=0,f=1;char ch; 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;} int n,m,k,ans,ans1; int head[N],pos;struct edge{int to,next,c;}e[M];void add(int a,int b,int c){pos++;e[pos].to=b,e[pos].next=head[a],e[pos].c=c,head[a]=pos;} queue<int>Q;bool vis[N];int dis[N]; vector<pa>G[N];void spfa(){ for(int i=1;i<=n;i++)dis[i]=inf,vis[i]=0; dis[1]=0,vis[1]=1;Q.push(1); while(!Q.empty()) { int u=Q.front();Q.pop();vis[u]=0; int size=G[u].size(); for(int j=0;j<size;j++) { pa v=G[u][j]; if(dis[v.first]>dis[u]+v.second) { dis[v.first]=dis[u]+v.second; if(!vis[v.first]) { vis[v.first]=1; Q.push(v.first); } } } }}void dfs(int u){ int size=G[u].size();vis[u]=1; for(int i=0;i<size;i++) { int v=G[u][i].first,c=G[u][i].second; if(vis[v]||dis[v]!=dis[u]+c) continue; add(u,v,c);add(v,u,c);dfs(v); }} int size[N],sum,f[N],rt;void find_root(int u,int fa){ size[u]=1,f[u]=0; for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(vis[v]||v==fa)continue; find_root(v,u);size[u]+=size[v]; f[u]=max(size[v],f[u]); }f[u]=max(f[u],sum-size[u]); if(f[rt]>f[u])rt=u;} struct node{int w,num;}d[N],p[N];int tot,t[N<<4][2],s[N<<4],all; void get_dep(int u,int fa){ p[++tot]=d[u]; for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(v==fa||vis[v])continue; d[v].num=d[u].num+1; d[v].w=d[u].w+e[i].c; get_dep(v,u); }}void cal(int u,int nowl,int nown){ d[u].w=nowl,d[u].num=nown; tot=0;get_dep(u,0); for(int i=1;i<=tot;i++) if(p[i].num<k) { int tmp=p[i].w+t[k-p[i].num][0]; if(tmp>ans)ans=tmp,ans1=t[k-p[i].num][1]; else if(tmp==ans)ans1+=t[k-p[i].num][1]; } else if(p[i].num==k) { if(p[i].w>ans)ans=p[i].w,ans1=1; else if(p[i].w==ans)ans1++; } for(int i=1;i<=tot;i++) if(p[i].num<=k) { if(p[i].w>t[p[i].num][0]) t[p[i].num][0]=p[i].w,t[p[i].num][1]=1; else if(p[i].w==t[p[i].num][0])t[p[i].num][1]++; s[++all]=p[i].num; }}void work(int u){ vis[u]=1;all=0; for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(vis[v])continue; cal(v,e[i].c,1); }for(int i=1;i<=all;i++)t[s[i]][0]=t[s[i]][1]=0; for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(vis[v])continue; sum=size[v],rt=0; find_root(v,0);work(rt); }} void find_dep(int u,int fa){ p[++tot]=d[u];s[++all]=d[u].w; for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(v==fa||vis[v])continue; d[v].w=d[u].w+e[i].c; find_dep(v,u); }} int main(){// freopen("in.txt","r",stdin);// freopen("my.txt","w",stdout); n=read(),m=read(),k=read()-1; for(int i=1;i<=m;i++) { int a=read(),b=read(),c=read(); G[a].push_back(make_pair(b,c)); G[b].push_back(make_pair(a,c)); } for(int i=1;i<=n;i++) sort(G[i].begin(),G[i].end()); spfa();for(int i=1;i<=n;i++)vis[i]=0; dfs(1);for(int i=1;i<=n;i++)vis[i]=0; sum=f[0]=n,rt=0;find_root(1,0);work(rt); memset(vis,0,sizeof(vis)); printf("%d %d\n",ans,ans1);}
0 0
- 【BZOJ 4016】[FJOI2014]最短路径树问题
- bzoj 4016: [FJOI2014]最短路径树问题
- BZOJ 4016: [FJOI2014]最短路径树问题
- 4016: [FJOI2014]最短路径树问题
- 4016: [FJOI2014]最短路径树问题
- bzoj 4016: [FJOI2014]最短路径树问题 最短路+点分治
- 【bzoj 4016】[FJOI2014]最短路径树问题 树分治+树形dp
- BZOJ4016: [FJOI2014]最短路径树问题
- FJOI2014最短路径树问题
- 【FJOI2014[bzoj4016]】最短路径树问题
- BZOJ4016: [FJOI2014]最短路径树问题
- [FJOI2014]最短路径树问题
- 4016: [FJOI2014]最短路径树问题 点分治
- 【树的分治】FJOI2014最短路径树问题
- 【BZOJ4016】【FJOI2014】 最短路径树问题 树的点分治
- [bzoj 4016] [Fjoi 2014] 最短路径树问题
- BZOJ 4016 最短路径树问题 [最短路+树分治]
- HYSBZ 4016最短路径树问题
- Unity NGUI 重叠的黑边
- js数组去重
- 连连看——C++简单小游戏
- 【codeforces 548B】Mike and Fun
- 超级课程表点赞插件
- bzoj 4016: [FJOI2014]最短路径树问题
- mysql 发生系统错误1067的解决方法
- Mac利用PD虚拟机安装Centos7
- 161221
- 微信小程序开发之页面分享 onShareAppMessage 分享参数用处
- faster-rcnn 之 RPN网络的结构解析以及RPN代码详解
- Android:初级控件之(一)ViewPager(一)
- web编程课程小结
- Android-聊聊MVC设计模式