zoukankan      html  css  js  c++  java
  • HDU4871 Shortest-path tree(点分治)

    题目

    题面

    大意是给你一个图,要你构建出一棵最短路树,再询问经过k个点的最长路径长度以及最长路径条数。

    思路

    点分治。
    点分治的思路是这样的:
    对于一个点(x)而言,对答案有影响的路径要么经过点(x)要么不经过,利用这点进行分治。
    点分治首先要找出一个重心。重心是指以该点为根所有的子树中sz最大的最小。
    然后,对于每一棵子树进行处理,统计答案(点分治题目不同的地方就在这,其它都是板子)
    之后再递归进重心的子树中处理。

    对于一个根来说,如果统计答案的复杂度是(O(n)),那么总的复杂度就是(O(nlogn)).

    代码

    #include<bits/stdc++.h>
    #define M 30005
    #define clr(x,y) memset(x,y,sizeof(x))
    using namespace std;
    int T,n,m,K;
    int g[M],tt;
    int ansa=0,ansc=0;//最长路,最长路的种数 
    struct Node{
    	int to,co;
    	bool operator < (const Node& res) const{
    		return to<res.to;	
    	}
    };
    vector<Node>G[M]; 
    struct edge{
    	int nxt,to,co;	
    }H[M<<1];
    void add(int a,int b,int c){
    	H[++tt]=(edge){g[a],b,c};
    	g[a]=tt;
    }
    struct node{
    	int x,ds;
    	bool operator < (const node& res) const{
    		return ds>res.ds;	
    	}
    };
    priority_queue<node>Q;
    int dis[M];
    bool vis[M];
    void Dij(){
    	clr(dis,0x3f);clr(vis,0);
    	dis[1]=0;
    	Q.push((node){1,0});
    	while(!Q.empty()){
    		node e=Q.top();Q.pop();
    		if(vis[e.x])continue;vis[e.x]=1;
    		for(int i=0;i<(int)G[e.x].size();i++){
    			int u=G[e.x][i].to,v=G[e.x][i].co;
    			if(dis[u]>dis[e.x]+v){
    				dis[u]=dis[e.x]+v;
    				Q.push((node){u,dis[u]});	
    			}
    		}
    	}
    }
    bool solved[M];
    int sz[M],ttot;
    void dfs(int x,int f,int ds){//构造树 
    	for(int i=0;i<(int)G[x].size();i++){
    		int u=G[x][i].to,v=G[x][i].co;
    		if(u==f||vis[u]||ds+v>dis[u])continue;
    		vis[u]=1;
    		add(u,x,v);add(x,u,v);
    		dfs(u,x,ds+v);
    	}
    }
    int mi=1e9,zx=1;
    void dfs_zx(int x,int f){//寻找重心 
    	sz[x]=1;int mm=0;
    	for(int i=g[x];i;i=H[i].nxt){
    		int u=H[i].to;
    		if(u==f||solved[u])continue;
    		dfs_zx(u,x);
    		sz[x]+=sz[u];
    		mm=max(mm,sz[u]);
    	}
    	mm=max(mm,ttot-sz[x]);
    	if(mm<mi)mi=mm,zx=x;
    }
    void find_zx(int rt){
    	mi=1e9,zx=1;
    	dfs_zx(rt,0);
    }
    void getans(int x,int y){
    	if(x>ansa)ansa=x,ansc=y;
    	else if(x==ansa)ansc+=y;
    }
    int mx[M],mn[M];
    int num[M],siz=0;
    void dfs_ans(int x,int f,int ds,int c){
    	dis[++siz]=ds;num[siz]=c;
    	for(int i=g[x];i;i=H[i].nxt){
    		int u=H[i].to,v=H[i].co;
    		if(solved[u]||u==f)continue;
    		dfs_ans(u,x,ds+v,c+1);	
    	}
    }
    void solve(int rt){
    	find_zx(rt);
    	solved[zx]=1;
    	for(int i=0;i<=K;i++)mx[i]=mn[i]=0;mn[0]=1;
    	for(int i=g[zx];i;i=H[i].nxt){
    		int u=H[i].to,v=H[i].co;
    		if(solved[u])continue;
    		siz=0;
    		dfs_ans(u,zx,v,1); 
    		for(int j=1;j<=siz;j++){
    			if(num[j]>=K)continue;
    			int tmp=K-1-num[j];
    			getans(mx[tmp]+dis[j],mn[tmp]);
    		}
    		for(int j=1;j<=siz;j++){
    			if(num[j]>=K)continue;
    			if(dis[j]>mx[num[j]]){
    				mx[num[j]]=dis[j];
    				mn[num[j]]=1;
    			}
    			else if(dis[j]==mx[num[j]])mn[num[j]]++;
    		}
    	}
    	ttot--;
    	for(int i=g[zx];i;i=H[i].nxt){
    		int u=H[i].to;
    		if(solved[u])continue;
    		solve(u);
    	}
    }
    int main(){
    	cin>>T;
    	while(T--){
    		clr(g,0);clr(solved,0);tt=ansa=ansc=0;
    		scanf("%d%d%d",&n,&m,&K);ttot=n;
    		for(int i=1;i<=n;i++)G[i].clear(); 
    		for(int i=1,a,b,c;i<=m;i++){
    			scanf("%d%d%d",&a,&b,&c);
    			G[a].push_back((Node){b,c});
    			G[b].push_back((Node){a,c});
    		}
    		for(int i=1;i<=n;i++)sort(G[i].begin(),G[i].end()); 
    		Dij();
    		clr(vis,0);dfs(1,0,0);
    		solve(1);
    		printf("%d %d
    ",ansa,ansc);
    	}
    	return 0;
    }
    
  • 相关阅读:
    CF 142B Tprimes
    CF 231A Team
    poj 2001 Shortest Prefixes ——字典树入门
    hdu 1039 Easier Done Than Said?
    poj 2528 Mayor's posters
    hdu 1061 Rightmost Digit
    poj 2503 Babelfish
    CF271 A. Beautiful Year
    poj 2752
    CF271 B. Prime Matrix
  • 原文地址:https://www.cnblogs.com/zryabc/p/10357173.html
Copyright © 2011-2022 走看看