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

Posted H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P2783 有机化学之神偶尔会作弊相关的知识,希望对你有一定的参考价值。

  题目传送门

  啦啦啦,发个文纪念一下第一道在洛谷上A的黑题,一次性就过真是无比舒服~(虽然某些大佬说这题有点水……)题目其实思路不难,Tarjan缩点+LCA,不过因为是无向边,所以在Tarjan的时候做点标记就行了,不过第四个点会被卡,用vector存边就可以A掉了。另外输出用二进制这个应该没什么好说的。

  下面放代码:

  

技术分享图片
#include<cmath>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=10001;
const int M=50001;
int n,m,T,indexx,id,dep[N];
int low[N],dfn[N],size[N];
int f[N][21],belong[N];
bool vis[N];
vector<int>edge[M<<1];
vector<int>node[M<<1];
stack<int>team;
inline int read()
{
  char ch=getchar();int num=0;bool flag=false;
  while(ch<0||ch>9){if(ch==-)flag=true;ch=getchar();}
  while(ch>=0&&ch<=9){num=num*10+ch-0;ch=getchar();}
  return flag?-num:num;
}
inline int Min(int x,int y)
{return x<y?x:y;}
inline void tarjan(int u,int last)
{
  dfn[u]=low[u]=++indexx;
  vis[u]=true;team.push(u);
  for(int i=0;i<node[u].size();i++){
    int v=node[u][i];
    if(v==last)continue;
    if(!dfn[v]){
      tarjan(v,u);
      low[u]=Min(low[u],low[v]);}
    else if(vis[v])
      low[u]=Min(low[u],dfn[v]);
  }
  if(dfn[u]==low[u]){
    int v;++id;
    do{
      v=team.top();team.pop();
      vis[v]=false;
      belong[v]=id;size[id]++;
    }while(v!=u);
  }
}
void build()
{
  for(int i=1;i<=n;i++)
    for(int j=0;j<node[i].size();j++){
      int v=node[i][j];
      if(belong[i]!=belong[v])
    edge[belong[i]].push_back(belong[v]);
    }
}
inline void dfs(int u,int fa,int depth)
{
  dep[u]=depth;f[u][0]=fa;
  for(int i=0;i<edge[u].size();i++)
    if(edge[u][i]!=fa)
      dfs(edge[u][i],u,depth+1);
}
void init()
{
  for(int j=1;j<=20;j++)
    for(int i=1;i<=id;i++)
      f[i][j]=f[f[i][j-1]][j-1];
}
inline int LCA(int a,int b)
{
  if(dep[a]<dep[b])swap(a,b);
  for(int i=20;i>=0;i--)
    if(dep[f[a][i]]>=dep[b])
      a=f[a][i];
  if(a==b)return a;
  for(int i=20;i>=0;i--)
    if(f[a][i]!=f[b][i])
      a=f[a][i],b=f[b][i];
  return f[a][0];
}
inline void print(int x)
{
  if(x==0)return;
  print(x>>1);
  putchar(x%2+0);
}
int main()
{
  n=read();m=read();
  for(int i=1;i<=m;i++){
    int x=read();int y=read();
    node[x].push_back(y);
    node[y].push_back(x);}
  for(int i=1;i<=n;i++)
    if(!dfn[i])tarjan(i,0);
  build();dfs(1,0,0);init();
  T=read();
  for(int i=1;i<=T;i++){
    int x=read();int y=read();
    x=belong[x],y=belong[y];
    int lca=LCA(x,y);
    print((dep[x]+dep[y])-(dep[lca]<<1)+1);
    printf("\n");
  }
  return 0;
}
View Code

 

以上是关于洛谷P2783 有机化学之神偶尔会作弊的主要内容,如果未能解决你的问题,请参考以下文章

p2783有机化学之神偶尔会做作弊

[luogu p2783]有机化学之神 (最水黑题)

markdown 打字稿...编码说明,提示,作弊,指南,代码片段和教程文章

洛谷——P1994 有机物燃烧

洛谷 P1994 有机物燃烧

洛谷P2784·图论·Spfa化学1(chem1)- 化学合成