• Tarjan+LCA【洛谷P2783】 有机化学之神偶尔会做作弊


    【洛谷P2783】 有机化学之神偶尔会做作弊

    题目背景

    XS中学化学竞赛组教练是一个酷爱炉石的人。

    有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹。

    然而你的化竞基友却向你求助了。

    “第1354题怎么做”<--手语 他问道。

    题目描述

    你翻到那一题:给定一个烃,只含有单键(给初中生的一个理解性解释:就是一堆碳用横线连起来,横线都是单条的)。

    然后炎魔之王拉格纳罗斯用他的火焰净化了一切环(???)。所有的环状碳都变成了一个碳。如图所示。

    然后指定多组碳,求出它们之间总共有多少碳。

    但是因为在考试,所以你只能把这个答案用手语告诉你的基友。你决定用二进制来表示最后的答案。如图所示(不要在意,和题目没有什么没关系)。

    输入输出格式

    输入格式:

    第一行两个整数n,m.表示有n个点,m根键

    接下来m行每行两个整数u,v表示u号碳和v号碳有一根键

    接下来一个整数tot表示询问次数

    接下来tot行每行两个整数,a,b表示询问的两个碳的编号

    输出格式:

    共tot行

    每行一个二进制数

    Tarjan+LCA。

    注意两个碳不成环,向Tarjan中传一个参数f,判一下v是不是等于f就好了。

    话说我WA了好多次、

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int wx=50017;
    inline int read(){
    	int sum=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
    	return sum*f;
    }
    int num,Num,tot,top,n,m,q,col,ans;
    int head[wx],h[wx],dep[wx],dfn[wx],low[wx],st[wx],belong[wx],f[wx][23];
    struct E{
    	int nxt,to;
    }e[wx*2];
    void up(int from,int to){
    	e[++Num].nxt=h[from];
    	e[Num].to=to;
    	h[from]=Num;
    }
    struct ee{
    	int nxt,to;
    }edge[wx*2];
    void add(int from,int to){
    	edge[++num].nxt=head[from];
    	edge[num].to=to;
    	head[from]=num;
    }
    void Tarjan(int u,int fa){
    	dfn[u]=low[u]=++tot;
    	st[++top]=u;
    	for(int i=h[u];i;i=e[i].nxt){
    		int v=e[i].to;
    		if(e[i].to==fa)continue;
    		if(!dfn[v]){
    			Tarjan(v,u);
    			low[u]=min(low[u],low[v]);
    		}
    		else if(!belong[v]){
    			low[u]=min(low[u],dfn[v]);
    		}
    	}
    	if(low[u]==dfn[u]){
    		belong[u]=++col;
    		while(st[top]!=u){
    			belong[st[top]]=col;
    			top--;
    		}
    		top--;
    	}
    }
    void dfs(int u,int fa){
    	dep[u]=dep[fa]+1;
    	for(int i=head[u];i;i=edge[i].nxt){
    		int v=edge[i].to;
    		if(v==fa)continue;
    		f[v][0]=u;
    		dfs(v,u);
    	}
    }
    void pre(){
    	for(int j=1;j<=21;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];
    }
    int LCA(int x,int y){
    	if(dep[x]<dep[y])swap(x,y);
    	for(int i=21;i>=0;i--)if(dep[f[x][i]]>=dep[y])x=f[x][i];
    	if(x==y)return x;
    	for(int i=21;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    	return f[x][0];
    }
    int main(){
    	n=read();m=read();
    	for(int i=1;i<=m;i++){
    		int x,y;
    		x=read();y=read();
    		up(x,y);up(y,x);
    	}
    	for(int i=1;i<=n;i++)if(!dfn[i])Tarjan(i,0);
    	for(int u=1;u<=n;u++){
    		for(int i=h[u];i;i=e[i].nxt){
    			int v=e[i].to;
    			if(belong[u]!=belong[v]){
    				add(belong[u],belong[v]);
    //				add(belong[v],belong[u]);
    			}
    		}
    	}
    	dfs(belong[1],0);pre();
    //	for(int i=1;i<=n;i++)printf("zz%d %d
    ",i,dep[i]);
    	q=read();
    	for(int i=1;i<=q;i++){
    		int x,y;
    		x=read();y=read();
    		x=belong[x];y=belong[y];
    		int lca=LCA(x,y);
    		int ans=dep[x]+dep[y]-2*dep[lca]+1;
    		int tmp=0,a[18];
    		while(ans){
    			a[++tmp]=ans%2;
    			ans/=2;
    		}
    		for(int i=tmp;i>=1;i--)printf("%d",a[i]);
    		puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    导入旧版本Android项目时的“Unable to resolve target ‘android
    eclipse打开文件目录
    ireport常见问题
    【技术贴】解决127.0.0.1和http://localhost均被拦截跳转到另一个网页
    【技术贴】SqlServer2008 R2 安装失败提示出现以下错误 服务 MSSQLSERVERO
    【技术贴】解决xp下Microsoft.SqlServer.Management.PSProvider.dll
    websphere性能设置和日常维护
    【技术贴】解决支付宝充值信用卡还款跳转到网上银行报错Error 404
    jQuery制作Facebook Timeline时间轴
    借助rownum中求Oracle表中前三名(三甲:状元榜眼探花)的方法(总计三种方法,以讲述rownum的使用为主)
  • 原文地址:https://www.cnblogs.com/wangxiaodai/p/9778895.html
Copyright © 2020-2023  润新知