无向图的双连通分量
1.点双连通分量 v-DCC
性质:1.顶点数不超过2
2.图中任意两点都同时包含在至少一个简单环中
3.如果该分量里有一个奇圈,那么其他所有点也必然在某个奇圈中;含有一个奇圈的充要条件是该分量不是二分图。
注意:割点的bccno可以是有多种选择,不一定是想要的那一个
最小方案数问题
hdu3844题目大意:有n条路矿井,每条路连接两个顶点,没有重边。你的任务是在节点处安装太平井,不得不管哪个连接点倒塌,不在此连接点的所有旷工都能到达太平井(只有倒塌的那条路不能走)。问,选择安装太平井的最小数目,和该数目下的最小方案数。
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN=1e5+100;
struct Edge{
int u,v;
};
int dfn[MAXN],iscut[MAXN],bccno[MAXN],dfs_clock,bcc_cnt;
vector<int> G[MAXN],bcc[MAXN];
stack<Edge> S;
int dfs(int u,int fa)
{
int lowu=dfn[u]=++dfs_clock;
int child=0;
int len=G[u].size();
for(int i=0;i<len;++i){
int v=G[u][i];
Edge e=(Edge){u,v};
if(!dfn[v]){
S.push(e);
child++;
int lowv=dfs(v,u);
lowu=min(lowu,lowv);
if(lowv>=dfn[u]){
iscut[u]=1;
bcc_cnt++;
for(;;){
Edge x=S.top(); S.pop();
if(bccno[x.u]!=bcc_cnt) { bcc[bcc_cnt].push_back(x.u); bccno[x.u]=bcc_cnt;}
if(bccno[x.v]!=bcc_cnt) { bcc[bcc_cnt].push_back(x.v); bccno[x.v]=bcc_cnt;}
if(x.u==u&&x.v==v) break;
}
}
}else if(dfn[v]<dfn[u]&&v!=fa){
S.push(e); lowu=min(dfn[v],lowu);
}
}
if(fa<0&&child==1) iscut[u]=0;
return lowu;
}