题解 P2783 【有机化学之神偶尔会做作弊】

钱逸凡

2018-11-08 12:35:51

Solution

又一道~~水~~黑题 # 思路: ## 显然的缩点+树剖/倍增求lca 由于是无向图,缩点时写法略有变化,即一个点和他的父亲不能构成强连通分量 缩点就这么写:~~(码风略丑)~~ ``` void dfs(int u,int fa){ vis[u]=1; dfn[u]=low[u]=++ti; st[++sttop]=u; inst[u]=1; for(int i=oldhead[u];i;i=nod[i].next){ int d=nod[i].v; if(d==fa)continue; if(!vis[d]){ dfs(d,u); low[u]=min(low[u],low[d]); } else if(inst[d])low[u]=min(low[d],low[u]); } if(dfn[u]==low[u]){ int now; taj++; do{ now=st[sttop--]; inst[now]=0; Belong[now]=taj; }while(now!=u); } } ``` 还有这奇怪的输出格式: ``` inline int out(int n){//输出n的二进制表示 int o=log2(n); for(;o>=0;o--){ if((1<<o)<=n){ n-=(1<<o); printf("1"); } else printf("0"); } printf("\n"); } ``` ------------ 完整代码: ``` #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; inline int Read(){ int x=0; char c=getchar(); while(c>'9'||c<'0')c=getchar(); while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); return x; } int toop,cnt; int oldhead[11010]; int head[10101]; struct Node{ int v; int next; }nod[101010],node[101010]; inline void ad(int u,int v){ nod[++toop].v=v; nod[toop].next=oldhead[u]; oldhead[u]=toop; }//旧图 inline void addedge(int u,int v){ node[++cnt].v=v; node[cnt].next=head[u]; head[u]=cnt; }//新图 inline void add(int u,int v){ ad(u,v); ad(v,u); }//旧图 inline void newadd(int u,int v){ addedge(u,v); addedge(v,u); }//新图 int n,m; int Belong[11010]; int vis[11010]; bool inst[10505]; int st[10101]; int sttop; int taj; int dfn[10101],low[10101],ti; void dfs(int u,int fa){ vis[u]=1; dfn[u]=low[u]=++ti; st[++sttop]=u; inst[u]=1; for(int i=oldhead[u];i;i=nod[i].next){ int d=nod[i].v; if(d==fa)continue; if(!vis[d]){ dfs(d,u); low[u]=min(low[u],low[d]); } else if(inst[d])low[u]=min(low[d],low[u]); } if(dfn[u]==low[u]){ int now; taj++; do{ now=st[sttop--]; inst[now]=0; Belong[now]=taj; }while(now!=u); } } void sd(){ int i,j; for(i=1;i<=n;i++)if(!vis[i])dfs(i,i); for(i=1;i<=n;i++){ for(j=oldhead[i];j;j=nod[j].next){ int d=nod[j].v; if(Belong[i]!=Belong[d]) newadd(Belong[i],Belong[d]); } } } int dep[10101],siz[10101],fa[10101],son[10101],top[10101]; void dfs1(int u){ siz[u]=1; for(int i=head[u];i;i=node[i].next){ int d=node[i].v; if(fa[u]!=d){ fa[d]=u; dep[d]=dep[u]+1; dfs1(d); siz[u]+=siz[d]; if(siz[d]>siz[son[u]])son[u]=d; } } } void dfs2(int u,int tp){ top[u]=tp; if(son[u])dfs2(son[u],tp); for(int i=head[u];i;i=node[i].next){ int d=node[i].v; if(fa[u]!=d&&son[u]!=d)dfs2(d,d); } } inline int lca(int u,int v){ while(top[u]!=top[v]){ if(dep[top[u]]>dep[top[v]])u=fa[top[u]]; else v=fa[top[v]]; } return dep[u]>dep[v]?v:u; } inline int out(int n){ int o=log2(n); for(;o>=0;o--){ if((1<<o)<=n){ n-=(1<<o); printf("1"); } else printf("0"); } printf("\n"); } int main(){ n=Read(),m=Read(); register int i; int u,v; for(i=1;i<=m;i++)u=Read(),v=Read(),ad(u,v); sd(); dep[1]=1; dfs1(1); dfs2(1,1); int q; q=Read(); while(q--){ u=Read(),v=Read(); u=Belong[u]; v=Belong[v]; out(dep[u]+dep[v]-2*dep[lca(u,v)]+1); } return 0; } ``` # ~~求赞~~