hdu 4871 Shortest-path tree 树分治
来源:互联网 发布:汉字笔顺演示软件下载 编辑:程序博客网 时间:2024/06/09 17:19
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4871
题目大意:给你一个图G,让你按照某种方式做一棵生成树,然后,在树上找含有K个节点的路径,使得路径最长,并输出最长路径的条数!
解题思路:还是树分治,而且是一个比较裸的树分治。对于当前的树,找到重心,然后处理与重心相连的所有节点,维护f[] 数组,f[i] 表示已经处理的子树中有i个节点的路径的最长的长度,r[] 数组表示已经处理的子树中有i个节点的最长路径的条数,然后暴力处理每一个子树!然后递归处理下去
//#pragma comment(linker,"/STACK:102400000,102400000")#include<stdio.h>#include<iostream>#include<string.h>#include<math.h>#include<algorithm>#include<vector>#include<map>#include<set>#include<queue>#include<string>#define ll long long#define db double#define PB push_backusing namespace std;const int N = 30005;const int M = 60006;const int INF = 1000000000;vector<int> v[N];int dist[N],bf[N],val[N];bool mk[N];void spfa(int n){ for(int i=1;i<=n;i++) dist[i]=INF; memset(mk,false,sizeof(mk)); memset(bf,-1,sizeof(bf)); mk[1]=true; dist[1]=0; queue<int> q; q.push(1); while(!q.empty()) { int t=q.front(); q.pop(); mk[t]=false; for(int i=0;i<v[t].size();i+=2) { int ed=v[t][i]; if(dist[ed]>dist[t]+v[t][i+1]) { dist[ed]=dist[t]+v[t][i+1]; val[ed]=v[t][i+1]; bf[ed]=t; if(!mk[ed]) mk[ed]=true,q.push(ed); }else if(dist[ed]==dist[t]+v[t][i+1]) { val[ed]=v[t][i+1]; if(bf[ed]==-1) bf[ed]=t; else bf[ed]=min(bf[ed],t); } } }}int head[N],to[M],next[M],cost[M],nedge;void init(){ memset(head,-1,sizeof(head)); nedge=0;}void add(int a,int b,int c){ to[nedge]=b,cost[nedge]=c,next[nedge]=head[a],head[a]=nedge++;}int max_node[N],tol[N],root,min_val;//INFbool vis[N];void get_root(int k,int &n){ tol[k]=1,max_node[k]=0; vis[k]=true; for(int i=head[k];i>=0;i=next[i]) { if(!vis[to[i]]) { get_root(to[i],n); max_node[k]=max(tol[to[i]],max_node[k]); tol[k]+=tol[to[i]]; } } max_node[k]=max(max_node[k],n-tol[k]); if(max_node[k]<min_val) { min_val=max_node[k]; root=k; } vis[k]=false;}int f[N],r[N];void get_f(int k,int sum){ f[k]=sum; vis[k]=true; for(int i=head[k];i>=0;i=next[i]) { if(!vis[to[i]]) { get_f(to[i],sum+1); f[k]=max(f[k],f[to[i]]); } } vis[k]=false;}bool cmp(int a,int b){ return f[to[a]]<f[to[b]];}int cnt,ch[N],g[N];void get_g(int k,int sum,int ct){ g[cnt]=sum,ch[cnt++]=ct; vis[k]=true; for(int i=head[k];i>=0;i=next[i]) { if(!vis[to[i]]) { get_g(to[i],sum+1,ct+cost[i]); } } vis[k]=false;}int num[N];int dep,max_k,ans;ll number;void work(int k,int n){ min_val=INF; get_root(k,n); int rt=root; vis[rt]=true; for(int i=head[rt];i>=0;i=next[i]) { if(!vis[to[i]]) { if(tol[to[i]]>tol[rt]) work(to[i],n-tol[rt]); else work(to[i],tol[rt]); } } int l=0; for(int i=head[rt];i>=0;i=next[i]) { if(!vis[to[i]]) { get_f(to[i],1); num[l++]=i; } } if(l==0) {vis[rt]=false;return;} sort(num,num+l,cmp); dep=f[to[num[l-1]]]; for(int i=1;i<=dep;i++) f[i]=-1; r[0]=1; for(int i=0;i<l;i++) { int ed=to[num[i]]; if(!vis[ed]) { cnt=0; get_g(ed,1,cost[num[i]]); for(int j=0;j<cnt;j++) { if(g[j]+1>max_k) continue; int t=max_k-g[j]-1; if(t<=dep&&f[t]!=-1) { if(f[t]+ch[j]>ans) { ans=f[t]+ch[j]; number=r[t]; }else if(f[t]+ch[j]==ans) { number+=r[t]; } } } for(int j=0;j<cnt;j++) { if(g[j]>max_k) continue; if(f[g[j]]==-1) f[g[j]]=ch[j],r[g[j]]=1; else { if(ch[j]>f[g[j]]) f[g[j]]=ch[j],r[g[j]]=1; else if(ch[j]==f[g[j]]) r[g[j]]++; } } } } vis[rt]=false;}int main(){#ifdef PKWV freopen("1011.in","r",stdin); freopen("out.out","w",stdout);#endif // PKWV int T; scanf("%d",&T); while(T--) { int n,m; scanf("%d%d%d",&n,&m,&max_k); for(int i=1;i<=n;i++) v[i].clear(); for(int i=0;i<m;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); v[a].PB(b),v[a].PB(c); v[b].PB(a),v[b].PB(c); } spfa(n); init(); for(int i=2;i<=n;i++) { add(i,bf[i],val[i]); add(bf[i],i,val[i]); } ans=0,number=0LL; work(1,n); printf("%d %I64d\n",ans,number); } return 0;}
0 0
- hdu 4871 Shortest-path tree 树分治
- HDU 4871 Shortest-path tree (树分治+SPFA)
- HDU 4871 Shortest-path tree (树分治之点分治 最短路径树问题)
- hdu 4871 Shortest-path tree(最短路+点分治)
- 【HDU】4871 Shortest-path tree 最短路+点分治
- HDU 4871 Shortest-path tree (最短路+树上点分治)
- HDU 4871 Shortest-path tree 最短路+树的点分治
- [HDOJ 4871] Shortest-path tree [树的分治+动态规划]
- hdu 4871 Shortest-path tree
- HDU 4871Shortest-path tree
- hdu 4871 Shortest-path tree
- 2014多校一1011(HDU4871)--Shortest-path tree树分治
- HDU4871 Shortest-path tree【最短路+点分治】
- hdu4871 Shortest-path tree
- HDU4871-Shortest-path tree
- hdu 3631 Shortest Path
- hdu 3631 Shortest Path
- hdu 3631 Shortest Path
- js操作cookie
- RailsCast26 Hackers Love Mass Assignment rails中按params创建、更新model时存在的安全隐患
- Linux下对磁盘分区、文件系统和目录结构认识
- java字符编码转换研究(转)
- js调试中的常见错误
- hdu 4871 Shortest-path tree 树分治
- [2014-09-02]JAVA笔记_枚举(Enumeration)
- J2SE复习之超类
- eclipse中Editors does not contain a main type 图解处理方法
- Ubuntu 开机自动挂载NTFS分区
- Practice-1
- C++泛型算法
- Longest Substring Without Repeating Characters Leetcode
- HDU 3996 Gold Mine(最小割---最大权闭合)