题目链接
题意
判断一个无向图是否为仙人掌图
- 强连通
- 一条边最多属于一个环
任意删边,求删边后图还是强连通(支撑子图)方案数
思路
如果这个图是仙人掌,帮所有环的边数+1相乘即可。
大数偷懒直接粘的别人代码(^_^)
据说数据弱代码可能有问题,又用点双写了一次,点双要求连通分量中边数等于点数,注意不要把只有两个点的加入判断(我这代码会帮割点和他儿子加入)
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
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;
const int N = 20005;
vector<int> e[N];
int sum[N], dep[N], d[N], flag, f[N];
void dfs(int u, int fa) {
dep[u] = dep[fa] + 1;
f[u] = fa;
for(auto v : e[u]) {
if(v == fa) continue;
if(!dep[v]) dfs(v, u);
else if(dep[v] < dep[u]){
sum[u] = dep[u]-dep[v]+1;
for(int i = u; i != v; i = f[i]) { // 点可以在多个环中,不要写成 i!=f[v] wa了半天
++d[i];
if(d[i] > 1) flag = 1;
}
}
}
}
int main() {
int n, m;
scanf("%d%d",&n,&m);
while(m--) {
int tmp, u, v;
scanf("%d%d",&tmp,&u);
while(--tmp) {
scanf("%d",&v);
e[u].push_back(v);
e[v].push_back(u);
u = v;
}
}
dfs(1,0);
for(int i = 1; i <= n; ++i) if(dep[i] == 0) flag = 1;
if(flag) return !printf("0\n");
ans.init();
for(int i = 1; i <= n; ++i) ans.mul(sum[i]+1ll);
ans.print();
return 0;
}
点双代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
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;
const int N = 20005;
vector<int> e[N], ds[N];
int low[N], dfn[N], tot, ds_cnt, book[N];
stack<int> st;
void tarjan(int u, int fa) {
low[u] = dfn[u] = ++tot;
st.push(u);
for(auto v : e[u]) {
if(v == fa) continue;
if(!dfn[v]) {
tarjan(v,u);
low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u]) {
++ds_cnt;
while(1) {
int now = st.top();
// printf("%d ",now);
st.pop();
ds[ds_cnt].push_back(now);
if(now == v) break;
}
// printf("%d -- %d\n",u,ds_cnt);
ds[ds_cnt].push_back(u);
}
}
else low[u] = min(low[u], dfn[v]);
}
}
int main() {
int n, m;
scanf("%d%d",&n,&m);
while(m--) {
int tmp, u, v;
scanf("%d%d",&tmp,&u);
while(--tmp) {
scanf("%d",&v);
e[u].push_back(v);
e[v].push_back(u);
u = v;
}
}
ans.init();
tarjan(1,1);
if(tot != n) return !printf("0\n");
for(int i = 1; i <= ds_cnt; ++i) {
int cnt = 0;
for(auto u : ds[i]) book[u] = 1;
for(auto u : ds[i]) for(auto v : e[u]) if(book[v]) ++cnt;
for(auto u : ds[i]) book[u] = 0;
// printf("%d %d\n",cnt,ds[i].size());
if(cnt/2 > ds[i].size()) return !printf("0\n");
if(cnt/2 == ds[i].size()) ans.mul(cnt/2+1);
}
ans.print();
return 0;
}