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

      

    自己还是太辣鸡了
  • 相关阅读:
    2014 10 07 ················男人感悟100(转自MOP)
    BFS和DFS优先搜索算法
    求素数算法-网摘
    DP问题各种模型的状态转移方程 (转)
    srand函数
    #include<algorithm>
    常用算法一(分治算法)
    杭电ACM题目分类
    四方定理
    五大常用算法之二:动态规划算法
  • 原文地址:https://www.cnblogs.com/zzyer/p/8531026.html
Copyright © 2011-2022 走看看