HDU4871 Shortest-path tree(最短路径树 + 树的点分治)
题目大概要先求一张边有权的图的根为1的最短路径树,要满足根到各点路径序列的字典序最小;然后求这棵最短路径树包含k个结点的最长路径的长度和个数。
首先先构造出这棵字典序最小的最短路径树。。好吧,我太傻逼了,不会。。保证邻接表存储邻接点有序的前提下,就能按字典序DFS一遍,在O(N+E)的时间复杂度上构造出来了。
然后就是统计路径最长长度和方案数,树上路径问题当然就是树分治了。
不多谈。。%¥……¥%……¥……连续写了200多行然后一直出数据调了2个多小时才AC。。
- #include<cstdio>
- #include<cstring>
- #include<queue>
- #include<algorithm>
- using namespace std;
- #define INF (1<<30)
- #define MAXN 33333
- #define MAXM 66666*2
- struct Edge{
- int v,w,next;
- }edge[MAXM];
- int NE,head[MAXN];
- void addEdge(int u,int v,int w){
- edge[NE].v=v; edge[NE].w=w;
- edge[NE].next=head[u]; head[u]=NE++;
- }
- int d[MAXN];
- bool vis[MAXN];
- void SPFA(int n){
- for(int i=; i<=n; ++i){
- d[i]=INF; vis[i]=;
- }
- d[]=; vis[]=;
- queue<int> que;
- que.push();
- while(!que.empty()){
- int u=que.front(); que.pop();
- for(int i=head[u]; i!=-; i=edge[i].next){
- int v=edge[i].v;
- if(d[v]>d[u]+edge[i].w){
- d[v]=d[u]+edge[i].w;
- if(!vis[v]){
- vis[v]=;
- que.push(v);
- }
- }
- }
- vis[u]=;
- }
- }
- struct Node{
- int u,v,w;
- bool operator<(const Node &nd)const{
- if(u==nd.u) return nd.v<v;
- return u<nd.u;
- }
- }node[MAXM];
- int cnt;
- void dfs(int u){
- vis[u]=;
- for(int i=head[u]; i!=-; i=edge[i].next){
- int v=edge[i].v;
- if(vis[v] || d[u]+edge[i].w!=d[v]) continue;
- node[cnt].u=u; node[cnt].v=v; node[cnt].w=edge[i].w;
- ++cnt;
- dfs(v);
- }
- }
- int size[MAXN];
- void getsize(int u,int fa){
- size[u]=;
- for(int i=head[u]; i!=-; i=edge[i].next){
- int v=edge[i].v;
- if(vis[v] || v==fa) continue;
- getsize(v,u);
- size[u]+=size[v];
- }
- }
- int mini,cen;
- void getcen(int u,int fa,int &tot){
- int res=tot-size[u];
- for(int i=head[u]; i!=-; i=edge[i].next){
- int v=edge[i].v;
- if(vis[v] || v==fa) continue;
- res=max(res,size[v]);
- getcen(v,u,tot);
- }
- if(res<mini){
- mini=res;
- cen=u;
- }
- }
- int getcen(int u){
- getsize(u,u);
- mini=INF;
- getcen(u,u,size[u]);
- return cen;
- }
- int k;
- int a_val[MAXN],a_cnt[MAXN],a_rec[MAXN],an,b_val[MAXN],b_cnt[MAXN],b_rec[MAXN],bn;
- bool tag[MAXN];
- int ans_val,ans_cnt;
- void conqur_dfs(int u,int fa,int val,int tot){
- if(b_val[tot]<val){
- b_val[tot]=val;
- b_cnt[tot]=;
- if(!tag[tot]){
- tag[tot]=;
- b_rec[bn++]=tot;
- }
- }else if(b_val[tot]==val){
- ++b_cnt[tot];
- }
- for(int i=head[u]; i!=-; i=edge[i].next){
- int v=edge[i].v;
- if(vis[v] || v==fa) continue;
- conqur_dfs(v,u,val+edge[i].w,tot+);
- }
- }
- void conqur(int u){
- an=;
- for(int i=head[u]; i!=-; i=edge[i].next){
- int v=edge[i].v;
- if(vis[v]) continue;
- bn=;
- conqur_dfs(v,v,edge[i].w,);
- for(int j=; j<bn; ++j){
- if(b_rec[j]==k-){
- if(b_val[b_rec[j]]>ans_val){
- ans_val=b_val[b_rec[j]];
- ans_cnt=b_cnt[b_rec[j]];
- }else if(b_val[b_rec[j]]==ans_val){
- ans_cnt+=b_cnt[b_rec[j]];
- }
- }else if(b_rec[j]<k-){
- int tmp=k--b_rec[j];
- if(a_cnt[tmp]==) continue;
- if(b_val[b_rec[j]]+a_val[tmp]>ans_val){
- ans_val=b_val[b_rec[j]]+a_val[tmp];
- ans_cnt=b_cnt[b_rec[j]]*a_cnt[tmp];
- }else if(b_val[b_rec[j]]+a_val[tmp]==ans_val){
- ans_cnt+=b_cnt[b_rec[j]]*a_cnt[tmp];
- }
- }
- }
- for(int j=; j<bn; ++j){
- int tmp=b_rec[j];
- tag[tmp]=;
- a_rec[an++]=tmp;
- if(a_val[tmp]<b_val[tmp]){
- a_val[tmp]=b_val[tmp];
- a_cnt[tmp]=b_cnt[tmp];
- }else if(a_val[tmp]==b_val[tmp]){
- a_cnt[tmp]+=b_cnt[tmp];
- }
- b_val[tmp]=;
- b_cnt[tmp]=;
- }
- }
- for(int i=; i<an; ++i){
- a_val[a_rec[i]]=;
- a_cnt[a_rec[i]]=;
- }
- }
- void divide(int u){
- u=getcen(u);
- vis[u]=;
- conqur(u);
- for(int i=head[u]; i!=-; i=edge[i].next){
- int v=edge[i].v;
- if(vis[v]) continue;
- divide(v);
- }
- }
- int main(){
- int t,n,m,a,b,c;
- scanf("%d",&t);
- while(t--){
- NE=;
- memset(head,-,sizeof(head));
- scanf("%d%d%d",&n,&m,&k);
- for(int i=; i<m; ++i){
- scanf("%d%d%d",&a,&b,&c);
- node[i<<].u=a; node[i<<].v=b; node[i<<].w=c;
- node[i<<|].u=b; node[i<<|].v=a; node[i<<|].w=c;
- }
- sort(node,node+(m<<));
- for(int i=; i<(m<<); ++i){
- addEdge(node[i].u,node[i].v,node[i].w);
- }
- SPFA(n);
- cnt=;
- memset(vis,,sizeof(vis));
- dfs();
- NE=;
- memset(head,-,sizeof(head));
- for(int i=; i<cnt; ++i){
- addEdge(node[i].u,node[i].v,node[i].w);
- addEdge(node[i].v,node[i].u,node[i].w);
- }
- memset(vis,,sizeof(vis));
- ans_val=; ans_cnt=;
- divide();
- printf("%d %d\n",ans_val,ans_cnt);
- }
- return ;
- }
HDU4871 Shortest-path tree(最短路径树 + 树的点分治)的更多相关文章
- 【CF938G】Shortest Path Queries(线段树分治,并查集,线性基)
[CF938G]Shortest Path Queries(线段树分治,并查集,线性基) 题面 CF 洛谷 题解 吼题啊. 对于每个边,我们用一个\(map\)维护它出现的时间, 发现询问单点,边的出 ...
- ZOJ 2760 How Many Shortest Path(最短路径+最大流)
Description Given a weighted directed graph, we define the shortest path as the path who has the sma ...
- Codeforces Round #329 (Div. 2) D. Happy Tree Party LCA/树链剖分
D. Happy Tree Party Bogdan has a birthday today and mom gave him a tree consisting of n vertecie ...
- HDU 4718 The LCIS on the Tree (动态树LCT)
The LCIS on the Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Oth ...
- hdu 5274 Dylans loves tree(LCA + 线段树)
Dylans loves tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- 程序员的算法课(19)-常用的图算法:最短路径(Shortest Path)
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/de ...
- LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板
P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...
- paip.tree 生成目录树到txt后的折叠查看
paip.tree 生成目录树到txt后的折叠查看 作者Attilax , EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.ne ...
- 【BZOJ2588】Count On a Tree(主席树)
[BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ...
- BZOJ_2212_[Poi2011]Tree Rotations_线段树合并
BZOJ_2212_[Poi2011]Tree Rotations_线段树合并 Description Byteasar the gardener is growing a rare tree cal ...
随机推荐
- Mac 下 gradle 路径
/Users/yourname/.gradle/wrapper/dists cmd:cd ~/.gradle/wrapper/dists/
- myeclipse相关
:) MyEclipse 10.7以后开始支持JDK1.7,修改settings下面的配置文件没卵用.
- mysql扩展库-1
启用mysql扩展库 在php.ini文件中去配置mysql扩展库 extension=php_mysql.dll 可以通过 phpinfo() 查看当前php支持什么扩展库. 在sql扩展库中创建一 ...
- jQuery – 3.JQuery的Dom操作
3.1 JQuery的Dom操作 1.使用html()方法读取或者设置元素的innerHTML 2.使用text()方法读取或者设置元素的innerText 3.使用attr() ...
- map find 是线程安全的吗
测试环境gcc4.8.2 iterator find ( const key_type& k ); const_iterator find ( const key_type& ...
- siblings 使用
//$(object).siblings().each(function () { // $(this).find("img").attr("class", & ...
- 【20140113-2】MyEclipse生成javadoc时出错:编码GBK的不可映射字符
今天生成java doc文档时,出现了如下所示的错误: 正在装入软件包 com.wisdom.test 的源文件...F:\workspace\StringUtils\src\com\wisdom\t ...
- [LeetCode] Validate Binary Search Tree (两种解法)
Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...
- NPOI读写Excel
1.整个Excel表格叫做工作表:WorkBook(工作薄),包含的叫页(工作表):Sheet:行:Row:单元格Cell. 2.NPOI是POI的C#版本,NPOI的行和列的index都是从0开始 ...
- NS2中trace文件分析
ns中模拟出来的时间最终会以trace文件的形式告诉我们,虽然说一般都是用awk等工具分析trace文件,但是了解trace文件的格式也是必不可少的.下面就介绍一下无线网络模拟中trace文件的格式. ...