链式前向星
有很多需要注意的:
第一种(更好用):
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;
}

浙公网安备 33010602011771号