[FJOI2014]最短路径树问题

V.[FJOI2014]最短路径树问题

这题已经在我的收藏夹里吃了大半年的灰了……主要是因为他们有人把这题归到了树形DP里面,然后我就傻乎乎地把它收藏了……

首先,假设我们已经求出了这个“最短路径树”,剩下的就是点分治的板子了。

而这个“最短路径树”,首先可以通过Dijkstra跑出最短路径DAG,然后在DAG上用bfs即可求出字典序最小的树。

总的来说似乎是把两道板子强行缝在了一起?老缝合怪了

代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,p;
namespace cd{
	int head[30100],cnt,buc[30100],bc[30100],sz[30100],msz[30100],ROOT,SZ,mx,ct;
	struct node{
		int to,next,val;
	}edge[60010];
	void ae(int u,int v,int w){
		edge[cnt].next=head[u],edge[cnt].to=v,edge[cnt].val=w,head[u]=cnt++;
		edge[cnt].next=head[v],edge[cnt].to=u,edge[cnt].val=w,head[v]=cnt++;
	}
	bool vis[30100];
	void getsz(int x,int fa){
		sz[x]=1;
		for(int i=head[x];i!=-1;i=edge[i].next)if(edge[i].to!=fa&&!vis[edge[i].to])getsz(edge[i].to,x),sz[x]+=sz[edge[i].to];
	}
	void getroot(int x,int fa){
		sz[x]=1,msz[x]=0;
		for(int i=head[x];i!=-1;i=edge[i].next)if(edge[i].to!=fa&&!vis[edge[i].to])getroot(edge[i].to,x),sz[x]+=sz[edge[i].to],msz[x]=max(msz[x],sz[edge[i].to]);
		msz[x]=max(msz[x],SZ-sz[x]);
		if(msz[x]<msz[ROOT])ROOT=x;
	}
	void get1(int x,int fa,int DEP,int DIS){
		if(DEP>p)return;
		if(mx<DIS+buc[p-DEP]&&bc[p-DEP])mx=DIS+buc[p-DEP],ct=0;
		if(mx==DIS+buc[p-DEP])ct+=bc[p-DEP];
		for(int i=head[x];i!=-1;i=edge[i].next)if(edge[i].to!=fa&&!vis[edge[i].to])get1(edge[i].to,x,DEP+1,DIS+edge[i].val);
	}
	void get2(int x,int fa,int DEP,int DIS){
		if(DEP>p)return;
		if(buc[DEP]<DIS)buc[DEP]=DIS,bc[DEP]=0;
		if(buc[DEP]==DIS)bc[DEP]++;
		for(int i=head[x];i!=-1;i=edge[i].next)if(edge[i].to!=fa&&!vis[edge[i].to])get2(edge[i].to,x,DEP+1,DIS+edge[i].val);
	}
	void work(int x){
		buc[0]=0,bc[0]=1;
		for(int i=head[x];i!=-1;i=edge[i].next)if(!vis[edge[i].to])get1(edge[i].to,x,1,edge[i].val),get2(edge[i].to,x,1,edge[i].val);
		for(int i=1;i<=p&&buc[i];i++)buc[i]=bc[i]=0;
	}
	void solve(int x){
		work(x),getsz(x,0),vis[x]=true;
		for(int i=head[x],y;i!=-1;i=edge[i].next){
			if(vis[y=edge[i].to])continue;
			ROOT=0,SZ=sz[y],getroot(y,x),solve(ROOT);
		}
	}
	void calc(){
		msz[0]=n+1,SZ=n,getroot(1,0),solve(ROOT);
	}
}
namespace Gra{
	int head[30100],cnt,dis[30100];
	struct node{
		int to,next,val;
	}edge[120010];
	void ae(int u,int v,int w){
		edge[cnt].next=head[u],edge[cnt].to=v,edge[cnt].val=w,head[u]=cnt++;
		edge[cnt].next=head[v],edge[cnt].to=u,edge[cnt].val=w,head[v]=cnt++;
	}
	bool vis[30100];
	void Dijkstra(){
		priority_queue<pair<int,int> >q;
		memset(dis,0x3f3f3f3f,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],y;i!=-1;i=edge[i].next)if(dis[y=edge[i].to]>dis[x]+edge[i].val)dis[y]=dis[x]+edge[i].val,q.push(make_pair(-dis[y],y));
		}
//		for(int i=1;i<=n;i++)printf("%d ",dis[i]);puts("");
	}
	void Build(){
		queue<int>q;q.push(1),memset(vis,false,sizeof(vis)),vis[1]=true;
		while(!q.empty()){
			int x=q.front();q.pop();
			vector<pair<int,int> >v;
			for(int i=head[x];i!=-1;i=edge[i].next)if(dis[edge[i].to]==dis[x]+edge[i].val)v.push_back(make_pair(edge[i].to,edge[i].val));
			sort(v.begin(),v.end());
			for(auto i:v)if(!vis[i.first])vis[i.first]=true,q.push(i.first),cd::ae(x,i.first,i.second);
		} 
	}
}
int main(){
	scanf("%d%d%d",&n,&m,&p),p--,memset(Gra::head,-1,sizeof(Gra::head)),memset(cd::head,-1,sizeof(cd::head));
	for(int i=1,x,y,z;i<=m;i++)scanf("%d%d%d",&x,&y,&z),Gra::ae(x,y,z);
	Gra::Dijkstra(),Gra::Build();
	cd::calc();
	printf("%d %d\n",cd::mx,cd::ct);
	return 0;
}

posted @ 2021-04-01 12:37  Troverld  阅读(73)  评论(0编辑  收藏  举报