zoukankan      html  css  js  c++  java
  • BZOJ 2125 最短路

    题解:建立圆方树,每个点向环内深度最浅的点连边

    分LCA是不是方点讨论即可

    如果是方点讨论从哪边绕过去的

    园点的话直接用最短路处理即可

    问题:双联通分量不熟

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<map>
    using namespace std;
    const int maxn=100009;
    const int inf=1000000000;
    
    int n,m,T;
    map<int,int>ma[maxn];
    
    struct Edge{
    	int from,to,dist;
    };
    vector<int>G[maxn];
    vector<Edge>edges;
    void Addedge(int x,int y,int z){
    	Edge e;
    	e.from=x;e.to=y;e.dist=z;
    	edges.push_back(e);
    	G[x].push_back(edges.size()-1);
    }
    
    queue<int>q;
    int inq[maxn];
    int d[maxn];
    void Spfa(){
    	for(int i=1;i<=n;++i){
    		d[i]=inf;inq[i]=0;
    	}
    	d[1]=0;inq[1]=1;q.push(1);
    	while(!q.empty()){
    		int x=q.front();q.pop();inq[x]=0;
    		for(int i=0;i<G[x].size();++i){
    			Edge e=edges[G[x][i]];
    			if(d[x]+e.dist<d[e.to]){
    				d[e.to]=d[x]+e.dist;
    				if(!inq[e.to]){
    					q.push(e.to);
    					inq[e.to]=1;
    				}
    			}
    		}
    	}
    }
    
    int dfsclock,scccnt;
    int pre[maxn],lowlink[maxn],ref[maxn];
    int lastpoint[maxn],restedge[maxn];
    int S[maxn],top;
    int dt[maxn];
    int vis[maxn];
    int depth[maxn];
    int father[maxn];
    vector<int>son[maxn];
    void Dfs(int u,int fa){
    //	printf("now in point %d
    ",u);
    //	for(int i=1;i<=5e8;++i);
    	pre[u]=lowlink[u]=++dfsclock;
    	ref[dfsclock]=u;
    	S[++top]=u;
    //	cout<<u<<' '<<S.size()<<endl;
    	
    	for(int i=0;i<G[u].size();++i){
    		Edge e=edges[G[u][i]];
    //		if(edges[G[u][i]^1].from==fa)continue;
    		int v=e.to;
    		if(v==fa)continue;
    		if(!pre[v]){
    			dt[v]=dt[u]+e.dist;
    			Dfs(v,u);
    			lowlink[u]=min(lowlink[u],lowlink[v]);
    		}else if(!vis[v]){
    //			cout<<u<<' '<<v<<endl;
    			lowlink[u]=min(lowlink[u],pre[v]);
    			restedge[u]=e.dist;
    			for(int i=top;S[i]!=v;--i){
    				int x=S[i];
    //				cout<<x<<' '<<v<<endl;
    				if(x==v)break;
    				father[x]=v;
    				lastpoint[x]=u;
    				son[v].push_back(x);
    //				printf("push(%d)
    ",x);
    //				if(S.size()==0)cout<<u<<endl;
    			}
    		}
    	}
    //	cout<<u<<" AFSD "<<S.size()<<endl;
    	if(lowlink[u]==pre[u]){
    		father[u]=fa;
    		son[fa].push_back(u);
    //		printf("push(%d)
    ",u);
    	}
    	--top;
    	vis[u]=1;
    //	printf("now out point %d
    ",u);
    }
    
    void Getdepth(int now,int fa){
    	depth[now]=depth[fa]+1;
    	for(int i=0;i<son[now].size();++i){
    		if(son[now][i]==fa)continue;
    		Getdepth(son[now][i],now);
    	}
    }
    
    int f[maxn][20];
    void LCAinit(){
    	for(int i=1;i<=n;++i)f[i][0]=father[i];
    	for(int j=1;j<=19;++j){
    		for(int i=1;i<=n;++i){
    			f[i][j]=f[f[i][j-1]][j-1];
    		}
    	}
    }
    int Getlca(int x,int y){
    	if(depth[x]<depth[y])swap(x,y);
    	for(int j=19;j>=0;--j){
    		if(depth[f[x][j]]>=depth[y])x=f[x][j];
    	}
    	if(x==y)return x;
    	for(int j=19;j>=0;--j){
    		if(f[x][j]!=f[y][j]){
    			x=f[x][j];y=f[y][j];
    		}
    	}
    	return f[x][0];
    }
    int Getpoint(int x,int y){
    	for(int j=19;j>=0;--j){
    		if(depth[f[x][j]]>depth[y])x=f[x][j];
    	}
    	return x;
    }
    
    int Getans(int x,int y){
    	if(depth[x]<depth[y])swap(x,y);
    	int lca=Getlca(x,y);
    //	cout<<"lca="<<lca<<endl;
    	if(lca==y){
    //		if(d[x]-d[y]==6760174)cout<<"AD"<<endl;
    		return d[x]-d[y];
    	}
    	
    	int px=Getpoint(x,lca);
    	int py=Getpoint(y,lca);
    	
    	if((lastpoint[px]!=lastpoint[py])||(lastpoint[px]==0)||(lastpoint[py]==0)){
    		return d[x]+d[y]-2*d[lca];
    	}else{
    		int ans=d[x]+d[y]-d[px]-d[py];
    		int tmp;
    		if(dt[px]>dt[py])tmp=dt[px]-dt[py];
    		else tmp=dt[py]-dt[px];
    //		printf("%d %d
    ",lastpoint[px],restedge[lastpoint[px]]);
    		int ans1=ans+tmp;
    		int ans2=ans+restedge[lastpoint[px]]+dt[lastpoint[px]]-dt[ref[lowlink[px]]]-tmp;//6760174
    		if(ans2==6760174){
    			printf("tmp=%d lastpoint=%d ref[]=%d
    ",tmp,lastpoint[py],ref[lowlink[px]]);
    		}
    		return min(ans1,ans2);
    	}
    }
    
    int main(){
    //	freopen("cactus.in","r",stdin);
    //	freopen("cactus.out","w",stdout);
    //	
    	scanf("%d%d%d",&n,&m,&T);
    	while(m--){
    		int x,y,z;
    		scanf("%d%d%d",&x,&y,&z);
    		if(ma[x].count(y)){
    			ma[x][y]=min(ma[x][y],z);
    		}else if(ma[y].count(x)){
    			ma[y][x]=min(ma[y][x],z);
    		}else{
    			ma[x][y]=z;
    		}
    	}
    	for(int i=1;i<=n;++i){
    		for(map<int,int>::iterator it=ma[i].begin();it!=ma[i].end();++it){
    			Addedge(i,it->first,it->second);
    			Addedge(it->first,i,it->second);
    		}
    	}
    	
    	Spfa();
    	Dfs(1,0);
    	Getdepth(1,0);
    	LCAinit();
    	
    //	for(int i=1;i<=n;++i)cout<<depth[i]<<' ';
    //	cout<<endl;
    	while(T--){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		printf("%d
    ",Getans(x,y));
    	}
    	
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    stringstream复用【原创】
    C++访问权限【原创】
    C++进阶阅读
    程序员的自我修养-装载、链接与库【原创】
    WinDebug 常用命令表【摘】
    重要说明与访问必看
    Beyond Compare V3.2.3 Beta 中文版
    Batch File Rename Utility(文件批量改名软件) 1.1.4231
    Defraggler(磁盘整理软件) V2.21.993 绿色版
    DiskGenius(磁盘分区/数据恢复) 32位 V4.9.1 免费绿色版
  • 原文地址:https://www.cnblogs.com/zzyer/p/8456376.html
Copyright © 2011-2022 走看看