图的表示
链式前向星:
struct edge
{
int to;
int w;
int next;
edge(){}
edge(int a,int b,int c){to=a;w=b;next=c;}
};
struct Map
{
int cnt;
int head[maxn];
edge e[maxn<<1];
void init(){cnt=0;memset(head,-1,sizeof(head));}
void add(int u,int v,int w)
{
e[cnt]=edge(v,w,head[u]);
head[u]=cnt++;
}
edge &operator[](int p){return e[p];}
};
图的强连通分支数
下面是一种dfs的o(n)的办法,该方法可能会炸栈。
int vis[maxn];
bool dfs(int rt,int fa)
{
if(vis[rt]==true)return true;
int s=vec[rt].size();
for(int i=0;i<s;i++)
{
int to=vec[rt][i];
if(to==fa)continue;
vis[rt]=vis[rt]||dfs(to);
vis[to]=true;
}
return vis[rt];
}
int getCc()
{
int ans=0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)if(dfs(i,-1)==false)ans++;
return ans;
}
下面是常用的并查集求联通分支:
int mset[maxn];
int find(int a)
{
return mset[a]==a?a:find(mset[a]);
}
void uni(int a,int b)
{
a=find(a);b=find(b);
if(a<b)mset[b]=a;
if(b<a)mset[a]=b;
}
int getCc()
{
for(int i=0;i<=n;i++)mset[i]=i;
for(int i=1;i<=n;i++)
{
int s=vec[i].size();
for(int j=0;j<s;j++)uni(i,vec[i][j]);
}
int ans=0;
for(int i=1;i<=n;i++)if(mset[i]==i)ans++;
return ans;
}