zoukankan      html  css  js  c++  java
  • 【BZOJ4016】[FJOI2014]最短路径树问题(点分治,最短路)

    【BZOJ4016】[FJOI2014]最短路径树问题(点分治,最短路)

    题面

    BZOJ
    洛谷

    题解

    首先把最短路径树给构建出来,然后直接点分治就行了。
    这个东西似乎也可以长链剖分,然而没有必要。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define MAX 30300
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int n,m,K;
    struct Line{int v,next,w;}e[MAX<<2];
    int h[MAX],cnt=1;
    inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;}
    vector<pair<int,int> > E[MAX<<1];
    int dis[MAX];
    bool vis[MAX];
    void Dijkstra()
    {
    	priority_queue<pair<int,int> >Q;
    	memset(dis,63,sizeof(dis));
    	Q.push(make_pair(0,1));dis[1]=0;
    	while(!Q.empty())
    	{
    		int u=Q.top().second;Q.pop();
    		if(vis[u])continue;vis[u]=true;
    		for(int i=h[u];i;i=e[i].next)
    		{
    			int v=e[i].v;
    			if(dis[v]>dis[u]+e[i].w)
    			{
    				dis[v]=dis[u]+e[i].w;
    				Q.push(make_pair(-dis[v],v));
    			}
    		}
    	}
    }
    void Build()
    {
    	priority_queue<int,vector<int>,greater<int> > Q;Q.push(1);
    	memset(vis,0,sizeof(vis));
    	while(!Q.empty())
    	{
    		int u=Q.top();Q.pop();vis[u]=true;
    		for(int i=h[u];i;i=e[i].next)
    		{
    			int v=e[i].v;if(vis[v])continue;
    			if(dis[v]==dis[u]+e[i].w)
    			{
    				E[u].push_back(make_pair(v,e[i].w));
    				E[v].push_back(make_pair(u,e[i].w));
    				if(!vis[v])Q.push(v),vis[v]=true;
    			}
    		}
    	}
    }
    int rt,Size,mx,sz[MAX];
    void getroot(int u,int ff)
    {
    	sz[u]=1;int ret=0;
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;if(v==ff||vis[v])continue;
    		getroot(v,u);sz[u]+=sz[v];
    		ret=max(ret,sz[v]);
    	}
    	ret=max(ret,Size-sz[u]);
    	if(mx>ret)mx=ret,rt=u;
    }
    int len[MAX],num[MAX],mxl;
    int Len[MAX],Num[MAX],Mxl;
    int av,as;
    void chk(int v,int s)
    {
    	if(av<v)av=v,as=0;
    	if(av==v)as+=s;
    }
    void dfs(int u,int ff,int l,int v)
    {
    	if(l>K)return;mxl=max(mxl,l);
    	if(len[l]==v)++num[l];
    	else if(len[l]<v)len[l]=v,num[l]=1;
    	if(l==K)chk(v,1);
    	else if(l<K&&Len[K-l])chk(Len[K-l]+v,Num[K-l]);
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int vv=e[i].v;if(vv==ff||vis[vv])continue;
    		dfs(vv,u,l+1,v+e[i].w);
    	}
    }
    void Divide(int u)
    {
    	vis[u]=true;Mxl=0;
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;if(vis[v])continue;
    		mxl=0;dfs(v,u,1,e[i].w);
    		for(int j=1;j<=mxl;++j)
    		{
    			if(Len[j]==len[j])Num[j]+=num[j];
    			else if(Len[j]<len[j])Len[j]=len[j],Num[j]=num[j];
    			num[j]=len[j]=0;
    		}
    		Mxl=max(Mxl,mxl);
    	}
    	for(int i=1;i<=Mxl;++i)Len[i]=Num[i]=0;
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;if(vis[v])continue;
    		Size=mx=sz[v];getroot(v,u);
    		Divide(rt);
    	}
    }
    int main()
    {
    	n=read();m=read();K=read()-1;
    	for(int i=1;i<=m;++i)
    	{
    		int u=read(),v=read(),w=read();
    		Add(u,v,w);Add(v,u,w);
    	}
    	Dijkstra();
    	Build();
    	memset(h,0,sizeof(h));cnt=1;
    	memset(vis,0,sizeof(vis));
    	for(int u=1;u<=n;++u)
    		for(int i=0,l=E[u].size();i<l;++i)
    			Add(u,E[u][i].first,E[u][i].second);
    	Size=mx=n;getroot(1,0);
    	Divide(rt);
    	printf("%d %d
    ",av,as);
    	return 0;
    }
    
  • 相关阅读:
    python基础--字典
    python基础--字符串
    windows系统下安装python解释器和PyCharm
    promise
    node之events 模块,并通过实例化 EventEmitter 类来绑定和监听事件
    node.js之CommonJS
    head first 设计模式笔记9-迭代器模式
    Codeforces 1256B Minimize the Permutation
    Codeforces 1256B Minimize the Permutation
    CCF CSP 201809-4 再卖菜
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10985306.html
Copyright © 2011-2022 走看看