BZOJ 4016 [FJOI2014]最短路径树问题

题解:构建最短路树,然后在上面点分治

一开始构建的思路是错的但是在Loj上A了

到现在还不明白为什么在BZOJ上T了QWQ,留坑

 不要以为自己想的是对的

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int maxn=200009;
const int oo=1000000000;
typedef pair<int,int> fuck;

int n,m,k;
int d[maxn];

int cntedge=0;
int head[maxn];
int to[maxn],nex[maxn],dist[maxn];
void Addedge(int x,int y,int z){
	nex[++cntedge]=head[x];
	to[cntedge]=y;
	dist[cntedge]=z;
	head[x]=cntedge;
}
vector<fuck>G[maxn];
struct HeapNode{
	int v,mindist;
	HeapNode(int x){
		v=x;mindist=d[x];
	}
	bool operator < (const HeapNode &rhs) const{
		return mindist>rhs.mindist;
	}
};
priority_queue<HeapNode>q;
int caled[maxn];

void Dijkstra(){
	for(int i=1;i<=n;++i)d[i]=oo;
	d[1]=0;q.push(HeapNode(1));
	while(!q.empty()){
		HeapNode x=q.top();q.pop();
		int u=x.v;
		if(caled[u])continue;
		caled[u]=1;
		for(int i=head[u];i;i=nex[i]){
			if(d[u]+dist[i]<d[to[i]]){
				d[to[i]]=d[u]+dist[i];
				q.push(HeapNode(to[i]));
			}
		}
	}
}


int nowsiz,root;
int g[maxn],siz[maxn],dep[maxn];
int vis[maxn];
void Getroot(int x,int fa){
	siz[x]=1;g[x]=0;
	for(int i=head[x];i;i=nex[i]){
		if(vis[to[i]])continue;
		if(to[i]==fa)continue;
		Getroot(to[i],x);
		siz[x]+=siz[to[i]];
		g[x]=max(g[x],siz[to[i]]);
	}
	g[x]=max(g[x],n-siz[x]);
	if(g[x]<g[root])root=x;
}

int maxlen=0;
long long tot=0;
int Tong[maxn][2];
pair<int,int>P[maxn];
int cnt;

void Getdep(int x,int fa){
	siz[x]=1;
	dep[x]=dep[fa]+1;
	++cnt;
	P[cnt]=make_pair(dep[x],d[x]);
	for(int i=head[x];i;i=nex[i]){
		if(to[i]==fa)continue;
		if(vis[to[i]])continue;
		d[to[i]]=d[x]+dist[i];
		Getdep(to[i],x);
		siz[x]+=siz[to[i]];
	}
}


void Cal(int x){
//	printf("Soling %d\n",x);
	int maxdep=0;
	d[x]=0;dep[x]=1;
	Tong[1][0]=0;
	Tong[1][1]=1;
	
	for(int i=head[x];i;i=nex[i]){
		if(vis[to[i]])continue;
		cnt=0;
		d[to[i]]=dist[i];
		Getdep(to[i],x);
//		for(int j=1;j<=cnt;++j)cout<<P[j].first<<' '<<P[j].second<<endl;
		for(int j=1;j<=cnt;++j){
			int a=P[j].first;
			int b=P[j].second;
			maxdep=max(maxdep,a);
			if(a>k)continue;
			if(b+Tong[k-a+1][0]>maxlen){
				maxlen=b+Tong[k-a+1][0];
				tot=Tong[k-a+1][1];
			}else if(b+Tong[k-a+1][0]==maxlen){
				tot+=Tong[k-a+1][1];
			}
		}
		for(int j=1;j<=cnt;++j){
			int a=P[j].first;
			int b=P[j].second;
			if(Tong[a][0]<b){
				Tong[a][0]=b;
				Tong[a][1]=1;
			}else if(Tong[a][0]==b){
				Tong[a][1]++;
			}
		}
	}
	for(int i=0;i<=maxdep;++i)Tong[i][0]=0,Tong[i][1]=0;
//	cout<<maxlen<<' '<<tot<<endl;
//	exit(0);
}

void Sol(int x){
	vis[x]=1;
	Cal(x);
	for(int i=head[x];i;i=nex[i]){
		if(vis[to[i]])continue;
		nowsiz=siz[to[i]];root=0;
		Getroot(to[i],x);
		Sol(root);
	}
}

void Dfs(int x){
	caled[x]=1;
	for(int i=0;i<G[x].size();++i){
		fuck e=G[x][i];
		if(caled[e.first])continue;
		Addedge(x,e.first,e.second);
		Addedge(e.first,x,e.second);
		Dfs(e.first);
	}
}
int main(){
	scanf("%d%d%d",&n,&m,&k);
	while(m--){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		Addedge(x,y,z);
		Addedge(y,x,z);
	}
	Dijkstra();
	for(int u=1;u<=n;++u){
		for(int i=head[u];i;i=nex[i]){
			if(d[u]+dist[i]==d[to[i]]){
				G[u].push_back(make_pair(to[i],dist[i]));
			}
		}
		sort(G[u].begin(),G[u].end());
	}
	cntedge=0;
	memset(caled,0,sizeof(caled));
	memset(head,0,sizeof(head));
	Dfs(1);
		
		
	for(int i=0;i<=n;++i)Tong[i][0]=0,Tong[i][1]=0;
	nowsiz=n;root=0;g[root]=oo;
	Getroot(1,0);
	Sol(root);
	
	cout<<maxlen<<' '<<tot<<endl;
	return 0;
}

  

posted @ 2018-03-08 21:40  ws_zzy  阅读(127)  评论(0编辑  收藏  举报