题意:
给出一个无向图,在判断原图是否为一个
仙人掌图的基础上,求仙人掌的支撑子图个数
支撑子图
:去掉一些边,但并不改变连通性,这样得到的子图为支撑子图。
题解:
1个仙人掌 <=> 连通性&点双均为简单环。
于是先dfs一次检验连通性,然后tarjan求点双,检验点双的点数=边数。
Ans=∏(环长+1)
A
n
s
=
∏
(
环
长
+
1
)
因为树边不可删除,每一个环上可以选择不删,也可以选择删除一条边,两条以上则破坏连通性。
需要使用高精度姿势,且标答数据错误。。。有前导0。。。但疼的一批。
Code:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2e4+100;
const int maxm = 1e6+100;
int first[maxn],des[maxm*2],nxt[maxm*2],tot;
int m,n;
int dfn[maxn],low[maxn],dfs_clock;
bool vis[maxn];
int bcc_cnt,bcc_no[maxn];
int st[maxm],top;
struct Big_Number{
LL a[1000],len;
const LL bas = 100000000;
void init(){
len=1;
memset(a,0,sizeof a);
a[0]=1;
}
void mul(LL val){
for (int i=0;i<len;i++){
a[i] = a[i]*val;
}
for (int i=0;i<len;i++){
a[i+1] += a[i]/bas;
a[i]%=bas;
}
while (a[len]){
a[len+1] = a[len]/bas;
a[len]%=bas;
len++;
}
}
void print(){
printf("%lld",a[len-1]);
for (int i=len-2;i>=0;i--){
printf("%.8lld",a[i]);
}
printf("\n");
}
}ans;
inline void addEdge(int x,int y){
tot++;
des[tot] =y;
nxt[tot] = first[x];
first[x] = tot;
}
void input(){
scanf("%d%d",&n,&m);
for (int i=0;i<m;i++){
int u,k;
scanf("%d%d",&k,&u);
for (int j=1;j<k;j++){
int v;
scanf("%d",&v);
addEdge(u,v);
addEdge(v,u);
u =v;
}
}
}
void dfs(int u){
vis[u] =1;
for (int t = first[u];t;t=nxt[t]){
int v = des[t];
if (vis[v])continue;
dfs(v);
}
}
bool dfs(int node,int fa,int Eid){
// cout<<"dfs: "<<node<<" "<<fa<<" "<<endl;
dfn[node] = low[node] = ++dfs_clock;
st[top++] = Eid;
for (int t = first[node];t;t=nxt[t]){
int v = des[t];
if (v==fa)continue;
if (!dfn[v]){
if (!dfs(v,node,t))return false;
low[node] = min(low[node],low[v]);
if (low[v]==dfn[node]){
// cout<<"find bcc:"<<node<<" "<<v<<endl;
bcc_cnt++;
LL e_cnt=1;
bool ok = true;
while (true){
int tt = st[--top];
if (bcc_no[des[tt]]!=bcc_cnt){
bcc_no[des[tt]] = bcc_cnt;
e_cnt++;
}else{
ok =false;
}
if (tt==t)break;
}
if (ok){
ans.mul(e_cnt);
}else{
return false;
}
}
}else if (dfn[v]<dfn[node]){
low[node] = min(low[node],dfn[v]);
st[top++] = t;
}
}
if (st[top-1]==Eid)top--;
return true;
}
void solve(){
dfs(1);
for (int i=1;i<=n;i++){
if (!vis[i]){
cout<<0<<endl;
return;
}
}
ans.init();
if (dfs(1,-1,-1)){
ans.print();
}else{
cout<<0<<endl;
}
}
int main(){
#ifdef debug
freopen("input.in","r",stdin);
#endif // debug
input();
solve();
return 0;
}