Tarjan+LCA【洛谷P2783】 有机化学之神偶尔会做作弊
2018-10-12 16:27
330 查看
【洛谷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\n",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; }
相关文章推荐
- Tarjan缩点+LCA【p2783】有机化学之神偶尔会做作弊
- 洛谷 P2783 有机化学之神偶尔会做作弊
- luogu P2783 有机化学之神偶尔会做作弊
- Tarjan缩点+LCA【洛谷P2416】 泡芙
- 洛谷P3345 [ZJOI2015]幻想乡战略游戏(动态点分治,树的重心,二分查找,Tarjan-LCA,树上差分)
- POJ 1330 Nearest Common Ancestors 【用Tarjan求LCA】
- Tarjan离线求LCA
- LCA 离线算法: tarjan
- 洛谷P1726 上白泽慧音(Tarjan强连通分量)
- poj 1470 Closest Common Ancestors 离线算法Tarjan求LCA
- poj 3529 Network 双连通分连 动态求桥的数目 + tarjan离线算法求LCA
- Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)
- [CF 191C]Fools and Roads[LCA Tarjan算法][LCA 与 RMQ问题的转化][LCA ST算法]
- Tarjan 离线算法LCA
- Network(Tarjan+LCA)
- poj3694 Network 无向图tarjan求桥+LCA
- LCA问题的ST,tarjan离线算法解法
- 洛谷 2921 记忆化搜索 tarjan 基环外向树
- Tarjan--LCA算法的个人理解即模板
- 洛谷 1262 间谍网络 Tarjan 图论