hdu4871 Shortest-path tree
来源:互联网 发布:mongodb 数据导出 编辑:程序博客网 时间:2024/06/10 03:04
题目:给你一个n个节点m条边的无向连通图,让你求一棵从以1为根节点的树,并且1到其余所有节点的距离都是最短路,距离相同的情况下要求字典序最小,最后在这棵树的基础上,找一条K个节点的简单路径,使得路径距离最长,问最长的距离是多少,这样的路径有多少条。
思路:先求出最短路,再dfs一次,找出字典序最小的树,最后点分治就行了
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<algorithm>#include<cstdio>#include<cmath>#include<cstring>#include<string>#include<vector>#include<map>#include<set>#include<queue>#include<stack>#include<list>#include<numeric>using namespace std;#define LL long long#define ULL unsigned long long#define INF 0x3f3f3f3f#define mm(a,b) memset(a,b,sizeof(a))#define PP puts("*********************");template<class T> T f_abs(T a){ return a > 0 ? a : -a; }template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}// 0x3f3f3f3f3f3f3f3f// 0x3f3f3f3fconst int maxn=3e4+50;const int maxe=2e5+50;struct EDGE{ int v,w,next;}E[maxe],edge[2*maxn];struct HeapNode{ int u,d; HeapNode(int u,int d):u(u),d(d){} HeapNode(){} bool operator<(const HeapNode &rhs)const{ return d>rhs.d; }};int first[maxn],ne;bool done[maxn];// 是否已永久标号int dist[maxn];// s到各个点的距离void add1(int u,int v,int w){ E[ne].v=v; E[ne].w=w; E[ne].next=first[u]; first[u]=ne++;}void dijkstra(int n){ priority_queue<HeapNode>Q; for(int i=1;i<=n;i++) dist[i]=INF; dist[1]=0; mm(done,0); Q.push(HeapNode(1,0)); while(!Q.empty()){ HeapNode x=Q.top();Q.pop(); int u=x.u; if(done[u]) continue; done[u]=true; for(int k=first[u];k!=-1;k=E[k].next){ EDGE &e=E[k]; if(dist[e.v]>dist[u]+e.w){ dist[e.v]=dist[u]+e.w; Q.push(HeapNode(e.v,dist[e.v])); } } }}int head[maxn],tol;//节点从1开始计数int son[maxn],f[maxn],vis[maxn];int dep[maxn],num[maxn],siz,d[maxn],dnum[maxn];int cntv,root,K,ans1,ans2;int Mx[maxn],Mn[maxn];void init(){ mm(head,-1);tol=0; mm(vis,0); f[0]=INF;//一定要初始化成一个很大的值}void addedge(int u,int v,int w){ edge[tol].v=v; edge[tol].w=w; edge[tol].next=head[u]; head[u]=tol++;}void getroot(int u,int fa){//寻找重心 son[u]=1,f[u]=0; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(v==fa||vis[v]) continue; getroot(v,u); son[u]+=son[v]; f[u]=max(f[u],son[v]); } f[u]=max(f[u],cntv-son[u]);//sum表示当前树的大小 if(f[u]<f[root]) root=u;//更新当前重心}void getdepth(int u,int fa){ dep[siz]=d[u]; num[siz++]=dnum[u]; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(v==fa||vis[v]) continue; d[v]=d[u]+edge[i].w; dnum[v]=dnum[u]+1; getdepth(v,u); }}void getans(int x,int y){ if(x>ans1){ ans1=x; ans2=y; } else if(x==ans1) ans2+=y;}void solve(int u){//计算以u为重心的树 vis[u]=1; for(int i=1;i<=K;i++) Mx[i]=Mn[i]=0; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(vis[v]) continue; d[v]=edge[i].w; dnum[v]=1; siz=0; getdepth(v,0); for(int j=0;j<siz;j++){ if(num[j]>=K) continue; if(num[j]+1==K) getans(dep[j],1); int pos=K-1-num[j]; getans(Mx[pos]+dep[j],Mn[pos]); } for(int j=0;j<siz;j++){ if(num[j]>=K) continue; if(dep[j]>Mx[num[j]]){ Mx[num[j]]=dep[j]; Mn[num[j]]=1; } else if(dep[j]==Mx[num[j]]) Mn[num[j]]++; } } for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(vis[v]) continue; cntv=son[v]; root=0; getroot(v,0); solve(root); }}vector<pair<int,int> > G[maxn];void gettree(int u){ done[u]=1; for(int j=0;j<G[u].size();j++){ int v=G[u][j].first,w=G[u][j].second; if(done[v]) continue; if(dist[u]+w==dist[v]){ addedge(u,v,w); addedge(v,u,w); gettree(v); } }}int main(){ int T,n,m,u,v,w; scanf("%d",&T); while(T--){ mm(first,-1);ne=0; scanf("%d%d%d",&n,&m,&K); for(int i=1;i<=n;i++) G[i].clear(); for(int i=1;i<=m;i++){ scanf("%d%d%d",&u,&v,&w); add1(u,v,w); add1(v,u,w); G[u].push_back(make_pair(v,w)); G[v].push_back(make_pair(u,w)); } dijkstra(n); init(); mm(done,0); for(int i=1;i<=n;i++) sort(G[i].begin(),G[i].end()); gettree(1); cntv=n; root=0; getroot(1,0); ans1=0,ans2=0; solve(root); printf("%d %d\n",ans1,ans2); } return 0;}
阅读全文
0 0
- hdu4871 Shortest-path tree
- HDU4871-Shortest-path tree
- 2014多校一1011(HDU4871)--Shortest-path tree树分治
- HDU4871 Shortest-path tree【最短路+点分治】
- hdu 4871 Shortest-path tree
- HDU 4871Shortest-path tree
- hdu 4871 Shortest-path tree
- hdu 4871 Shortest-path tree 树分治
- Shortest Path
- Shortest Path
- Shortest Path
- [HDOJ 4871] Shortest-path tree [树的分治+动态规划]
- hdu 4871 Shortest-path tree(最短路+点分治)
- 【HDU】4871 Shortest-path tree 最短路+点分治
- HDU 4871 Shortest-path tree (最短路+树上点分治)
- HDU 4871 Shortest-path tree (树分治+SPFA)
- hdoj 3631 Shortest Path
- hdu 3631 Shortest Path
- Lua 5.3 源码分析(四)线程 lua_State
- Tomcat出现中文乱码问题
- 强叔侃墙_出口选路_策略路由_基于源IP地址的策略路由
- occ
- 汉化版svn安装包和英文对比
- hdu4871 Shortest-path tree
- 服务端开发常用技术
- 初学Json
- 嵌入式系统学习——arm-qtopia添加应用
- 阿里云
- WdatePicker时间控件的使用
- 阿里云发布企业级ECS产品线,释放技术升级红利,最高降价35%
- WebRTC之WebRtcVideoEngine2模块(六)
- 批量处理AS文件编码问题