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

    bzoj
    luogu
    loj

    description

    给你一张(n)(m)条边的无向图,从(1)号点出发沿着最短路走到每一个节点,若最短路有多条则走节点编号字典序最小的那条。可以证明走过的边是一棵树。求这棵树上所有包含(k)个节点的简单路径的最长长度以及这样的路径条数。
    (nle30000,mle60000,2le k le n)

    sol

    强行二合一而已。
    先对原图跑一边(Dijkstra)求出到每个点的最短路,然后(dfs)一遍就可以把最短路树给建出来。
    对于路径统计的问题,考虑点分治,每次统计所有过重心的路径,开一个桶表示到重心经过的边数为(i)的最大长度以及方案数。每次要先更新答案再加入桶避免重复计算。

    code

    由于bzoj评测机的某种玄学操作,只要在结构体里面调用递归函数就会出错。
    所以以下这份代码无法在bzoj上AC。
    不过在luogu和loj上都可以AC呀。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    int gi(){
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    #define pi pair<int,int>
    #define mk make_pair
    const int N = 150000;
    int n,m,k;pi ans;
    void upt(pi &a,pi b){
    	if (a.first<b.first) a=b;
    	else if (a.first==b.first) a.second+=b.second;
    }
    struct Tree{
    	int to[N],nxt[N],ww[N],head[N],cnt,sz[N],w[N],vis[N],sum,root;pi f[N];
    	void link(int u,int v,int w){
    		to[++cnt]=v;nxt[cnt]=head[u];ww[cnt]=w;head[u]=cnt;
    	}
    	void getroot(int u,int fa){
    		sz[u]=1;w[u]=0;
    		for (int e=head[u];e;e=nxt[e])
    			if (to[e]!=fa&&!vis[to[e]]){
    				getroot(to[e],u);
    				sz[u]+=sz[to[e]];
    				w[u]=max(w[u],sz[to[e]]);
    			}
    		w[u]=max(w[u],sum-sz[u]);
    		if (w[u]<w[root]) root=u;
    	}
    	void query(int u,int fa,int dep,int dis){
    		upt(ans,mk(dis+f[k-dep].first,f[k-dep].second));
    		if (k==dep) return;
    		for (int e=head[u];e;e=nxt[e])
    			if (to[e]!=fa&&!vis[to[e]])
    				query(to[e],u,dep+1,dis+ww[e]);
    	}
    	void modify(int u,int fa,int dep,int dis){
    		upt(f[dep],mk(dis,1));if (k==dep) return;
    		for (int e=head[u];e;e=nxt[e])
    			if (to[e]!=fa&&!vis[to[e]])
    				modify(to[e],u,dep+1,dis+ww[e]);		
    	}
    	void clear(int u,int fa,int dep,int dis){
    		f[dep]=mk(0,0);if (k==dep) return;
    		for (int e=head[u];e;e=nxt[e])
    			if (to[e]!=fa&&!vis[to[e]])
    				clear(to[e],u,dep+1,dis+ww[e]);		
    	}
    	void solve(int u){
    		vis[u]=1;upt(f[0],mk(0,1));
    		for (int e=head[u];e;e=nxt[e])
    			if (!vis[to[e]]) query(to[e],0,1,ww[e]),modify(to[e],0,1,ww[e]);
    		for (int e=head[u];e;e=nxt[e])
    			if (!vis[to[e]]) clear(to[e],0,1,ww[e]);
    		for (int e=head[u];e;e=nxt[e])
    			if (!vis[to[e]]) root=0,sum=sz[to[e]],getroot(to[e],0),solve(root);
    	}
    	void work(){
    		w[0]=sum=n;getroot(1,0);solve(root);
    		printf("%d %d
    ",ans.first,ans.second);
    	}
    }T;
    struct Graph{
    	int to[N],nxt[N],ww[N],head[N],cnt,dis[N],vis[N],dfn[N],tim;
    	vector<int>v[N];
    	priority_queue<pi,vector<pi>,greater<pi> >Q;
    	void link(int u,int v,int w){
    		to[++cnt]=v;nxt[cnt]=head[u];ww[cnt]=w;head[u]=cnt;
    	}
    	void dfs(int u){
    		dfn[u]=++tim;
    		for (int e=head[u];e;e=nxt[e])
    			if (dis[to[e]]==dis[u]+ww[e])
    				v[u].push_back(to[e]);
    		sort(v[u].begin(),v[u].end());
    		for (int i=0,sz=v[u].size();i<sz;++i)
    			if (!dfn[v[u][i]]){
    				T.link(u,v[u][i],dis[v[u][i]]-dis[u]);
    				T.link(v[u][i],u,dis[v[u][i]]-dis[u]);
    				dfs(v[u][i]);
    			}
    	}
    	void work(){
    		memset(dis,63,sizeof(dis));
    		dis[1]=0;Q.push(mk(0,1));
    		while (!Q.empty()){
    			int u=Q.top().second;Q.pop();
    			if (vis[u]) continue;vis[u]=1;
    			for (int e=head[u];e;e=nxt[e])
    				if (dis[to[e]]>dis[u]+ww[e])
    					dis[to[e]]=dis[u]+ww[e],Q.push(mk(dis[to[e]],to[e]));
    		}
    		dfs(1);
    	}
    }G;
    int main(){
    	n=gi();m=gi();k=gi()-1;
    	for (int i=1;i<=m;++i){
    		int u=gi(),v=gi(),w=gi();
    		G.link(u,v,w);G.link(v,u,w);
    	}
    	G.work();T.work();return 0;
    }
    
  • 相关阅读:
    radio切换,点击方法onclick
    Android Studio 使用小技巧和快捷键
    Linux命令(1)——xargs命令
    Java-多线程基本
    POJ 2031 Building a Space Station(最小生成树)
    《iOS Human Interface Guidelines》——Popover
    Android在使用WebView时,通过Javascript调用JAVA函数
    Mysql文章笔记
    大量高清文字版PDF编程书籍下载
    Scala函数特性
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9247879.html
Copyright © 2011-2022 走看看