zoukankan      html  css  js  c++  java
  • HDU 3686 Traffic Real Time Query System (图论)

    HDU 3686 Traffic Real Time Query System

    题目大意

    给一个N个点M条边的无向图,然后有Q个询问X,Y,问第X边到第Y边必需要经过的点有多少个。

    solution

    显然园方树+tarjan求LCA,然后求两条边之间的点
    必经的点的数量就是圆点的数量,然后进行分类讨论

    • (LCA)为圆点:
      那么其中一个点到(LCA)的圆点数量为((deep[x] - deep[lca])/2),因为(LCA)为圆点被算了两遍,所以要-1
    • (LCA)为方点:
      那么其中一个点到(LCA)的圆点数量为((deep[x] - deep[lca]- 1)/2),那么两个点之间的圆点数量就是((deep[x] + deep[y] - 2 * deep[lca])- 1)

    由此可见,两种情况算下来,答案的式子是一样的,所以直接上板子算答案就行了,这道题的代码还是比较考验码力的……

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    #define v e[i].to
    const int maxn=10000+3,maxe=100000+3;
    int n,m,tot,head[maxn],h[2*maxn],js,dfs_clock,deep[2*maxn],father[2*maxn];
    int bcc_cnt,sta[maxn],top,dfn[maxn],low[maxn];
    bool vis[2*maxn];
    
    struct edge{
    	int from,to,next;
    }e[2*maxe],ed[2*maxe];
    
    inline void Add(int a,int b){//原图
    	e[++tot].from=a;
    	e[tot].to=b;
    	e[tot].next=head[a];
    	head[a]=tot;
    }
    
    inline void Add2(int a,int b){//圆方树
    	ed[++js].from=a;
    	ed[js].to=b;
    	ed[js].next=h[a];
    	h[a]=js;
    }
    
    inline void tarjan(int u){
    	low[u]=dfn[u]=++dfs_clock;
    	sta[++top]=u;
    	for(int i=head[u];i;i=e[i].next){
    		if(dfn[v]) low[u]=min(low[u],dfn[v]);
    		else{
    			tarjan(v);
    			low[u]=min(low[v],low[u]);
    			if(low[v]==dfn[u]){
    				++bcc_cnt;
    				int temp;
    				do{
    					temp=sta[top];
    					top--;
    					Add2(n+bcc_cnt,temp);
    					Add2(temp,n+bcc_cnt);
    				}while(temp!=v);
    				Add2(u,n+bcc_cnt);
    				Add2(n+bcc_cnt,u);
    			}
    		}
    	}
    }
    
    inline void init(){
    	tot=0; js=0; top=0; dfs_clock=0; bcc_cnt=0;
    	memset(head,0,sizeof(head));
    	memset(e,0,sizeof(e));
    	memset(h,0,sizeof(h));
    	memset(ed,0,sizeof(ed));
    	memset(sta,0,sizeof(sta));
    	memset(dfn,0,sizeof(dfn));
    	memset(low,0,sizeof(low));
    	memset(deep,0,sizeof(deep));
    	memset(vis,0,sizeof(vis));
    	memset(father,0,sizeof(father));
    	memset(sta,0,sizeof(sta));
    }
    
    inline void dfs(int x){
    	vis[x]=1;
    	for(int i=h[x];i;i=ed[i].next){
    		int now=ed[i].to;
    		if(vis[now]) continue;
    		deep[now]=deep[x]+1;
    		father[now]=x;
    		dfs(now);
    	}
    }
    
    inline int find(int a,int b){//非倍增也可
    	if(deep[a]<deep[b]) swap(a,b);
    	while(deep[a]>deep[b]) a=father[a];
    	while(a!=b){
    		a=father[a];
    		b=father[b];
    	}
    	return a;
    }
    
    inline int len(int a,int b){
    	int lca=find(a,b);
    	return (deep[a]+deep[b]-2*deep[lca])/2-1;
    }
    
    int main(){
    	while(1){
    		scanf("%d%d",&n,&m);
    		if(n==0&&m==0) return 0;
    		init();
    		for(int i=1;i<=m;i++){
    			int x,y;
    			scanf("%d%d",&x,&y);
    			Add(x,y);
    			Add(y,x);
    		}
    		for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
    		for(int i=1;i<=n+bcc_cnt;i++) if(!vis[i]) dfs(i);
    		int t;
    		scanf("%d",&t);
    		while(t--){
    			int x,y;
    			scanf("%d%d",&x,&y);
    			int a=e[x*2].from,b=e[x*2].to,c=e[y*2].from,d=e[y*2].to; //枚举节点
    			printf("%d
    ",max(max(len(b,d),len(a,d)),max(len(b,c),len(a,c))));
    		}
    	}
    }
    

    提交语言GCC、GCC、GCC!!!
    md重要的事情说三遍,淦……

  • 相关阅读:
    HTTP请求 GET POST 网络编程实现(转)
    较老版本 AFNetworking 使用心得
    优秀java开源项目与解决方案推荐与概论
    URL的格式scheme
    用MATLAB实现字符串分割
    matlab search path
    matlab中的字符串数组与函数调用
    全新重装win8.1系统后 配置开发及办公环境步骤
    html图片上下翻滚展示代码
    html目录树的操作
  • 原文地址:https://www.cnblogs.com/rui-4825/p/12843809.html
Copyright © 2011-2022 走看看