zoukankan      html  css  js  c++  java
  • P2993 [FJOI2014]最短路径树问题

    题目

    P2993 [FJOI2014]最短路径树问题

    给定一个无向图,求出其最短路径树上面的,包含 (k) 个点的一条路径,使得这条路径权值尽可能大,并求出有多少条长度为这个的路径(不要求为 (k) 个点)。

    分析

    没意思题,点分治+最短路。

    先直接跑最短路后建出树来。

    然后如果把点数当作边权,把路径权值当作价值,题目就相当于是P4149 [IOI2011]Race求最大值了。

    然后求出最大值后,考虑统计答案,相当于就是统计树上距离为 (D) 的点对个数,模板。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    inline void read(T &x){
        x=0;char ch=getchar();bool f=false;
        while(!isdigit(ch)) f|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=f?-x:x;return;
    }
    template <typename T>
    inline void write(T x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10^48);
    	return;
    }
    const int N=2e5+5,INF=1e9+7;
    int n,m,k;
    int head[N],nex[N],to[N],w[N],idx;
    int dis[N],vis[N],pre[N],val[N];
    int t[N],Vis[N],t1[N],tot[N],tmp;
    int Ans,Num,Root,Max,Size,siz[N],son[N];
    inline void add(int x,int y,int z){idx++;nex[idx]=head[x];head[x]=idx;to[idx]=y;w[idx]=z;}
    priority_queue<pair<int,int> >q;
    inline void GetRoot(int x,int fa){
    	siz[x]=1;son[x]=0;
    	for(int i=head[x];i;i=nex[i]){
    		int t=to[i];
    		if(t==fa||vis[t])continue;
    		GetRoot(t,x);siz[x]+=siz[t];
    		if(son[x]<siz[t]) son[x]=siz[t];
    	}
    	if(son[x]<Size-siz[x]) son[x]=Size-siz[x];
    	if(Max>son[x])Max=son[x],Root=x;
    	return ;
    }
    inline void Calc(int x,int fa,int dist,int dep){
    	if(t1[dep]<dist) t1[dep]=dist,tot[dep]=1;
    	else if(t1[dep]==dist)	tot[dep]++;
    	if(dep>tmp)tmp=dep;
    	for(int i=head[x];i;i=nex[i]){
    		int t=to[i];
    		if(t==fa||vis[t])continue;
    		Calc(t,x,dist+w[i],dep+1);
    	}
    	return ;
    }
    inline void DFS(int x){
    	Vis[0]=vis[x]=true;
    	int dep=0;
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];tmp=0;
    		if(vis[y])continue;
    		Calc(y,x,w[i],1);
    		if(tmp>dep) dep=tmp;
    		for(int j=1;j<=tmp;j++){
    			if(Vis[k-1-j]){
    				if(Ans<t1[j]+t[k-1-j]) Ans=t1[j]+t[k-1-j],Num=tot[j]*Vis[k-1-j];
    				else if(Ans==t1[j]+t[k-1-j]) Num+=tot[j]*Vis[k-1-j];
    			}
    		}
    		for(int j=1;j<=tmp;j++){
    			if(t1[j]>t[j]) t[j]=t1[j],Vis[j]=tot[j];
    			else if(t1[j]==t[j]) Vis[j]+=tot[j];
    		}
    		for(int j=1;j<=tmp;j++) t1[j]=tot[j]=0;
    	}
    	for(int i=0;i<=dep;i++) t[i]=Vis[i]=0;
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(vis[y])continue;
    		Root=0,Max=INF,Size=siz[y];
    		GetRoot(y,x);
    		DFS(Root);
    	}
    	return ;
    }
    void Dijkstra(){
    	memset(dis,0x3f,sizeof(dis));
    	dis[1]=0;q.push(make_pair(0,1));
    	while(!q.empty()){
    		int x=q.top().second;q.pop();
    		if(vis[x]) continue;
    		vis[x]=true;
    		for(int i=head[x];i;i=nex[i]){
    			int t=to[i];
    			if(dis[t]>dis[x]+w[i]){
    				dis[t]=dis[x]+w[i],pre[t]=x,val[t]=w[i];
    				q.push(make_pair(-dis[t],t));
    			}
    			else if(dis[t]==dis[x]+w[i]&&w[i]>val[t]) pre[t]=x,val[t]=w[i];
    		}
    	}
    	idx=0;memset(head,0,sizeof(head));
    	for(int i=2;i<=n;i++) add(i,pre[i],val[i]),add(pre[i],i,val[i]);
    	return ;
    }
    int main(){
    	read(n),read(m),read(k);
    	for(int i=1;i<=m;i++){
    		int x,y,z;
    		read(x),read(y),read(z);
    		add(x,y,z),add(y,x,z);
    	}
    	Dijkstra();
    	Max=INF,Size=n,Root=0;
    	memset(vis,0,sizeof(vis));
    	GetRoot(1,0);
    	DFS(Root);
    	write(Ans),putchar(' '),write(Num);
    	return 0;
    }
    
  • 相关阅读:
    新概念英语(1-121)The man in a hat
    新概念英语(1-119)who call out to the thieves in the dark?
    画像分析(1-1)如何为客户画像?
    大数据分析师
    英语词汇(2)fall down,fall off和fall over
    把梳子卖给和尚的故事
    洛谷P1970 花匠(dp)
    2018.10.24模拟赛2解题报告
    2018.10.24模拟赛1解题报告
    洛谷P1941 飞扬的小鸟(背包 dp)
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14726844.html
Copyright © 2011-2022 走看看