zoukankan      html  css  js  c++  java
  • [BZOJ2125]最短路

    Description
    给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径。

    Input
    输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个整数v,u,w表示一条无向边v-u,长度为w 最后Q行,每行两个整数v,u表示一组询问

    Output
    输出Q行,每行一个整数表示询问的答案

    Sample Input
    9 10 2
    1 2 1
    1 4 1
    3 4 1
    2 3 1
    3 7 1
    7 8 2
    7 9 2
    1 5 3
    1 6 4
    5 6 1
    1 9
    5 7

    Sample Output
    5
    6

    HINT
    对于100%的数据,N<=10000,Q<=10000


    这题写的我真TM舒服……

    首先对仙人掌建出一棵圆方树,考虑树上的边权,如果是圆点连圆点,则边权不变;如果是圆点连方点,则边权为圆点到方点所属环上,dfs序最小的点的距离

    然后我们考虑lca的两种情况,如果lca是圆点,那么我们直接输出圆方树上的两点之间距离;如果lca是方点,我们找到(x,y)在lca儿子中的祖先节点(x',y'),则答案为(dis_{x ightarrow x'}+dis_{x' ightarrow y'}+dis_{y' ightarrow y})

    (树剖求lca找(x',y')时细节贼难受……)

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define Fi first
    #define Se second
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef pair<int,int>pii;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int frd(){
    	int x=0,f=1; char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<3)+(x<<1)+ch-'0';
    	return x*f;
    }
    inline int read(){
    	int x=0,f=1; char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<3)+(x<<1)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)	putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=1e4;
    int V[N+10],cnt,n,m,q;
    struct node{
    	int lca,x,y;
    	node(){lca=x=y=0;}
    	node(int _l,int _x,int _y){lca=_l,x=_x,y=_y;}
    	void insert(int _l,int _x,int _y){lca=_l,x=_x,y=_x;}
    };
    struct S1{	
    	int pre[(N<<2)+10],now[(N<<1)+10],child[(N<<2)+10],val[(N<<2)+10],tot;
    	int fa[(N<<1)+10],deep[(N<<1)+10],top[(N<<1)+10],Rem[(N<<1)+10],size[(N<<1)+10],dis[(N<<1)+10];
    	void join(int x,int y,int z){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=z;}
    	void insert(int x,int y,int z){join(x,y,z),join(y,x,z);}
    	void dfs(int x){
    		deep[x]=deep[fa[x]]+1,size[x]=1;
    		for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
    			if (son==fa[x])	continue;
    			fa[son]=x,dis[son]=dis[x]+val[p];
    			dfs(son),size[x]+=size[son];
    			if (size[Rem[x]]<size[son])	Rem[x]=son;
    		}
    	}
    	void build(int x){
    		if (!x)	return;
    		top[x]=Rem[fa[x]]==x?top[fa[x]]:x;
    		build(Rem[x]);
    		for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
    			if (son==fa[x]||son==Rem[x])	continue;
    			build(son);
    		}
    	}
    	node LCA(int x,int y){
    		int lastx=0,lasty=0;
    		while (top[x]!=top[y]){
    			if (deep[top[x]]<deep[top[y]])	lasty=top[y],y=fa[top[y]];
    			else	lastx=top[x],x=fa[top[x]];
    		}
    		if (x==y)	return node(x,lastx,lasty);
    		if (deep[x]<deep[y])	return node(x,lastx,Rem[x]);
    		else	return node(y,Rem[y],lasty);
            //WA了好几次,画了图才发现应该这样写……
    	}
    }RST;//Round Square Tree
    struct S2{
    	int pre[(N<<2)+10],now[N+10],child[(N<<2)+10],val[(N<<2)+10];
    	int fa[N+10],dfn[N+10],low[N+10],fv[N+10],dis[N+10],stack[N+10],belong[N+10];
    	bool instack[N+10];
    	int tot,Time,top,num;
    	void join(int x,int y,int z){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=z;}
    	void insert(int x,int y,int z){join(x,y,z),join(y,x,z);}
    	int distant(int x,int y,int pos){
    		if (dfn[x]<dfn[y])	swap(x,y);
    		return min(dis[x]-dis[y],V[pos]-(dis[x]-dis[y]));
    	}
    	void dfs(int x){
    		dfn[x]=++Time;
    		for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
    			if (son==fa[x])	continue;
    			if (!dfn[son]){
    				fa[son]=x,dis[son]=dis[x]+val[p];
    				fv[son]=val[p],dfs(son);
    			}else	if (dfn[son]<dfn[x]){
    				V[++cnt]=val[p],RST.insert(cnt+n,son,0);
    				for (int i=x;i!=son;i=fa[i])	V[cnt]+=fv[i];
    				for (int i=x;i!=son;i=fa[i])	RST.insert(cnt+n,i,distant(i,son,cnt));
    			}
    		}
    	}
    	void tarjan(int x,int fa){//不论如何枚举顺序都是一样的,那么dfn就算再次dfs也是一样的
    		dfn[x]=low[x]=++Time;
    		instack[stack[++top]=x]=1;
    		for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
    			if (son==fa)	continue;
    			if (!dfn[son])	tarjan(son,x),low[x]=min(low[x],low[son]);
    			else	if (instack[son])	low[x]=min(low[x],dfn[son]);
    		}
    		if (dfn[x]==low[x]){
    			belong[x]=++num;
    			instack[x]=0;
    			while (stack[top]!=x)	belong[stack[top]]=num,instack[stack[top--]]=0;
    			top--;
    		}
    	}
    	void init(){
    		Time=0;
    		memset(dfn,0,sizeof(dfn));
    	}
    }OT;//Original Tree
    struct S3{
    	int x,y,z;
    	void insert(int _x,int _y,int _z){x=_x,y=_y,z=_z;}
    }Line[(N<<1)+10];
    int main(){
    	n=read(),m=read(),q=read();
    	for (int i=1;i<=m;i++){
    		int x=read(),y=read(),z=read();
    		OT.insert(x,y,z);
    		Line[i].insert(x,y,z);
    	}
    	OT.dfs(1),OT.init(),OT.tarjan(1,0);
    	for (int i=1;i<=m;i++)
    		if (OT.belong[Line[i].x]!=OT.belong[Line[i].y])
    			RST.insert(Line[i].x,Line[i].y,Line[i].z);
    	RST.dfs(1),RST.build(1);
    	for (int i=1;i<=q;i++){
    		int x=read(),y=read();
    		node tmp=RST.LCA(x,y);
    		if (tmp.lca<=n)	printf("%d
    ",RST.dis[x]+RST.dis[y]-2*RST.dis[tmp.lca]);
    		else{
    			int res=RST.dis[x]+RST.dis[y]-RST.dis[tmp.x]-RST.dis[tmp.y];
    			res+=OT.distant(tmp.x,tmp.y,tmp.lca-n);
    			printf("%d
    ",res);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Mysql查询语句,select,inner/left/right join on,group by.....[例题及答案]
    Java IO实现文件(及文件夹)的复制 原创代码【精】
    [精华帖]Java接口怎么定义?如何使用?【实例讲解】
    Java面向对象中this关键字详解 意义+实例讲解【hot】
    linux系统编程之进程(三):进程复制fork,孤儿进程,僵尸进程
    linux系统编程之进程(二):进程生命周期与PCB(进程控制块)
    linux系统编程之进程(一):进程与程序
    linux系统编程之文件与IO(八):文件描述符相关操作-dup,dup2,fcntl
    linux系统编程之文件与IO(七):时间函数小结
    linux系统编程之文件与IO(六):实现ls -l功能
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/10279492.html
Copyright © 2011-2022 走看看