洛谷 P2783 有机化学之神偶尔会做作弊 做题记录

前置芝士:强联通分量、LCA

思路

先缩点,然后图就变成了一颗树,答案就是树上最短路 +1,因为两个端点都要算上。
值得注意的是虽然是无向图,但是没有重边/自环,所以不用考虑边的编号,直接考虑父节点就好了。
时间复杂度:\(O(n\log n)\)
难点/坑点:

  • 缩完点之后要记得编号都已经变了,注意输入的 \(a\)\(b\)
点击查看代码
#include<bits/stdc++.h>

#define ll long long
#define i128 __int128

#define mem(a,b) memset((a),(b),sizeof(a))
#define m0(a) memset((a),0,sizeof(a))
#define m1(a) memset(a,-1,sizeof(a))
#define lb(x) ((x)&-(x))
#define lc(x) ((x)<<1)
#define rc(x) (((x)<<1)|1)
#define pb(G,x) (G).push_back((x))
#define For(a,b,c) for(int a=(b);a<=(c);a++)
#define Rep(a,b,c) for(int a=(b);a>=(c);a--)
#define in1(a) a=read()
#define in2(a,b) a=read(), b=read()
#define in3(a,b,c) a=read(), b=read(), c=read()

using namespace std;

int read() {
	int x=0,f=1; char c=getchar();
	for(;c<'0'||c>'9';c=getchar()) f=(c=='-'?-1:1); 
	for(;c<='9'&&c>='0';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	return x*f;
}
void write(int x) { if(x>=10) write(x/10); putchar('0'+x%10); }

const int mod = 998244353;
int qpo(int a,int b) {int res=1; for(;b;b>>=1,a=(a*a)%mod) if(b&1) res=res*a%mod; return res; }
int inv(int a) {return qpo(a,mod-2); }

#define maxn 10100
int n,m;
vector<int >G[maxn];
int u[maxn*5],v[maxn*5];

int dfn[maxn],low[maxn],dcnt;
int inst[maxn],stk[maxn],stop;
int bel[maxn],btop;

void Tarjan(int u,int fa) {
	dfn[u]=low[u]=++dcnt;
	stk[++stop]=u; inst[u]=1;
	for(auto v:G[u]) {
		if(v==fa) continue;
		if(!dfn[v]) Tarjan(v,u),low[u]=min(low[u],low[v]);
		else if(inst[v]) low[u]=min(low[u],dfn[v]);
	}
	if(dfn[u]==low[u]) {
		++btop;
		while(1) {
			int v=stk[stop--];
			inst[v]=0;
			bel[v]=btop;
			if(u==v) break;
		}
	}
}

int fa[26][maxn],dep[maxn];

int lg2(int x) {
	int res=0;
	if(x&0xffff0000) res+=16,x>>=16;
	if(x&0x0000ff00) res+=8,x>>=8;
	if(x&0x000000f0) res+=4,x>>=4;
	if(x&0x0000000c) res+=2,x>>=2;
	if(x&0x00000002) res+=1,x>>=1;
	return res;
}

void dfs(int u,int f) {
	fa[0][u]=f; dep[u]=dep[f]+1;
	int k=lg2(dep[u]);
	For(i,1,k) fa[i][u]=fa[i-1][fa[i-1][u]];
	for(auto v:G[u]) if(v!=f) dfs(v,u);
}
int LCA(int x,int y) {
	if(dep[x]<dep[y]) swap(x,y);
	while(dep[x]>dep[y]) x=fa[lg2(dep[x]-dep[y])][x];
	if(x==y) return x;
	int k=lg2(dep[x]);
	Rep(i,k,0) if(fa[i][x]!=fa[i][y]) x=fa[i][x],y=fa[i][y];
	return fa[0][x];
}
int dis(int x,int y) {
	return dep[x]+dep[y]-2*dep[LCA(x,y)];
}

int qwq[33],xtop;
void bir(int x) {
	m0(qwq); xtop=0;
	while(x) {
		qwq[++xtop]=x%2;
		x/=2;
	}
	Rep(i,xtop,1) cout<<qwq[i];
	puts("");
}

void work() {
	in2(n,m);
	For(i,1,m) {
		in2(u[i],v[i]);
		G[u[i]].push_back(v[i]);
		G[v[i]].push_back(u[i]);
	}
	For(i,1,n) if(!dfn[i]) Tarjan(1,0);
	For(i,1,n) G[i].clear();
	For(i,1,m) {
		u[i]=bel[u[i]],v[i]=bel[v[i]];
		if(u[i]!=v[i]) {
			G[u[i]].push_back(v[i]);
			G[v[i]].push_back(u[i]);
		} 
	}
	dfs(1,0);
	int q=read();
	while(q--) {
		int a,b;
		in2(a,b);
		a=bel[a],b=bel[b];
		bir(dis(a,b)+1);
	}
}

signed main() {
//	ios::sync_with_stdio(false); 
//	cin.tie(0); cout.tie(0);
	int _=1;
//	int _=read();
	For(i,1,_) {
		work();
	}
	return 0;
}
posted @ 2024-11-23 13:43  coding_goat_qwq  阅读(2)  评论(0编辑  收藏  举报