链式前向星

有很多需要注意的:


第一种(更好用):

  1.建边时\(base=0\)(注意\(cnt\)从1开始)

ll cnt=1;
void add(ll u,ll v){
	e[++cnt].nxt=head[u];
	head[u]=cnt;
	e[cnt].to=v;
}

  2.遍历时模版写法

for(ll i=head[x];i;i=e[i].nxt){
	if(i!=(fa[x]^1)){
		ll y=e[i].to;
		if(!vis[y]){
			fa[y]=i;
			dfs1(y);
		}
	}
}

  3.head数组无需初始化.

例题:

  【模板】边双连通分量是第一次用第一种链式前向星:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn1=5e5+5,maxn2=2e6+5;
bool cut[maxn2<<1];
ll n,m,cnt=1,tot,k,head[maxn1],fa[maxn1],dfn[maxn1],low[maxn1],scc[maxn1];
struct node{
	ll to,nxt;
}e[maxn2<<1];
vector<ll> ans[maxn1];
void add(ll u,ll v){
	e[++cnt].nxt=head[u];
	head[u]=cnt;
	e[cnt].to=v;
}
void dfs1(ll x){
	dfn[x]=low[x]=++tot;
	for(ll i=head[x];i;i=e[i].nxt){
		if(i!=(fa[x]^1)){
			ll y=e[i].to;
			if(!dfn[y]){
				fa[y]=i;
				dfs1(y);
				low[x]=min(low[x],low[y]);
				if(dfn[x]<low[y]){
					cut[fa[y]]=cut[fa[y]^1]=true;
				}
			}else{
				low[x]=min(low[x],dfn[y]);
			}
		}
	}
}
void dfs2(ll x){
	scc[x]=k;
	for(ll i=head[x];i;i=e[i].nxt){
		ll y=e[i].to;
		if(!scc[y]&&!cut[i]){
			dfs2(y);
		}
	}
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>n>>m;
	for(ll i=1;i<=m;i++){
		ll u,v;
		cin>>u>>v;
		add(u,v);
		add(v,u);
	}
	for(ll i=1;i<=n;i++){
		if(!dfn[i]){
			dfs1(i);
		}
	}
	for(ll i=1;i<=n;i++){
		if(!scc[i]){
			k++;
			dfs2(i);
		}
	}
	cout<<k<<"\n";
	for(ll i=1;i<=n;i++){
		ans[scc[i]].push_back(i);
	}
	for(ll i=1;i<=k;i++){
		cout<<ans[i].size()<<" ";
		for(auto j:ans[i]){
			cout<<j<<" ";
		}
		cout<<"\n";
	}
	return 0;
}

第二种:

  1.建边时\(base=0\)

void ade(ll u,ll v){
	e[cnt].nxt=head[u];
	head[u]=cnt;
	e[cnt++].to=v;
}

  2.遍历时模版写法

for(ll i=head[x];~i;i=e[i].nxt){
    if(i!=(fa[x]^1)){
        ll y=e[i].to;
        fa[y]=i;
        dfs(y);
    }
}

  3.head数组初始化成\(-1\)

memset(head,-1,sizeof(head));

例题:

  旅游航道是第一次用第二种链式前向星:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=3e4+5;
bool cut[maxn<<1];
ll n,m,ans,cnt,tot,dfn[maxn],low[maxn],head[maxn],fa[maxn];
struct node{
	ll to,nxt;
}e[maxn<<1];
void ade(ll u,ll v){
	e[cnt].nxt=head[u];
	head[u]=cnt;
	e[cnt++].to=v;
}
void dfs(ll x){
	dfn[x]=low[x]=++tot;
	for(ll i=head[x];~i;i=e[i].nxt){
		if(i!=(fa[x]^1)){
			ll y=e[i].to;
			if(!dfn[y]){
				fa[y]=i;
				dfs(y);
				low[x]=min(low[x],low[y]);
				if(dfn[x]<low[y]){
					cut[fa[y]]=cut[fa[y]^1]=true;
				}
			}else{
				low[x]=min(low[x],dfn[y]);
			}
		}
	}
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	while(cin>>m>>n&&m&&n){
		tot=cnt=ans=0;
		memset(dfn,0,sizeof(dfn));
		memset(head,-1,sizeof(head));
		memset(cut,0,sizeof(cut));
		memset(fa,0,sizeof(fa));
		for(ll i=1;i<=n;i++){
			ll u,v;
			cin>>u>>v;
			ade(u,v);
			ade(v,u);
		}
		for(ll i=1;i<=m;i++){
			if(!dfn[i]){
				dfs(i);
			}
		}
		for(ll i=0;i<n*2;i++){
			if(cut[i]){
				ans++;
			}
		}
		cout<<ans/2<<"\n";
	}
	return 0;
}
posted @ 2026-10-17 16:26  beiciqi  阅读(3)  评论(0)    收藏  举报