zoukankan      html  css  js  c++  java
  • [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;
    }
    

  • 相关阅读:
    win10补丁导致打印机无法共享
    EdgexGo2.0学习-14 EdgeX2.0 AppService导出到Mqtt
    EdgexGo2.0学习-13 EdgeX2.0 编译Appservice
    winform程序在系统缩放150%时右边留空白问题解决办法
    Linux嵌入式串口转网络
    Win10 磁盘变成文件夹
    Win10下使用Gitblit
    JMeter学习笔记——Web接口测试(webservice)
    jmeter之__RandomFromMultipleVars函数使用详解
    jmeter——参数化——$__RandomFromMultipleVars()函数
  • 原文地址:https://www.cnblogs.com/Troverld/p/14605788.html
Copyright © 2011-2022 走看看