Gym 101334C 无向仙人掌
给出图,求他的“仙人掌度”,即求包括他自身的生成子图有多少?
只能删去仙人掌上的叶子的一条边,然后根据乘法原理相乘;
1、怎么求一个仙人掌叶子上有多少边? 可以利用点,边双连通的时间戳这个概念,但是绝对时间是不对的,只能用相对的时间戳。
2、怎么把第二种情况剔除掉? 就是记录每一个点加入环中的次数;
3、第三种情况,就是判连通了;
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 20000 + 5; 6 7 struct Sol { 8 vector<int> G[maxn]; 9 int cyclecnt; 10 int cycle[maxn]; 11 int dfn[maxn]; 12 int c[maxn]; 13 int n; 14 int num[maxn]; 15 16 void init(int n) { 17 this->n = n; 18 for(int i=0; i<=n; i++) 19 G[i].clear(); 20 memset(dfn,0,sizeof(dfn)); 21 memset(cycle,0,sizeof(cycle)); 22 memset(num,0,sizeof(num)); 23 cyclecnt = 0; 24 dfn[1] = 1; 25 } 26 27 void AddEdge (int from,int to) { 28 G[from].push_back(to); 29 G[to].push_back(from); 30 } 31 32 void dfs(int u,int fa) { 33 for(int i=0; i<G[u].size(); i++) { 34 int v = G[u][i]; 35 if(v==fa) continue; 36 37 if(!dfn[v]) { 38 dfn[v] = dfn[u] + 1; 39 dfs(v,u); 40 c[u]+=c[v]; 41 } else if(dfn[v]<dfn[u]) { 42 cycle[cyclecnt++] = dfn[u] - dfn[v] + 2; 43 c[u]++; 44 c[v]--; 45 } 46 } 47 } 48 49 void ans() { 50 for(int i=1; i<=n; i++) 51 if(c[i]>1||dfn[i]==0) { 52 puts("0"); 53 return; 54 } 55 //int res = 1; 56 //for(int i=0;i<cyclecnt;i++) 57 // res = res * cycle[i]; 58 //return res; 59 60 int len = 0; 61 num[0] = 1; 62 63 for(int i=0; i<cyclecnt; i++) { 64 65 for(int j=0; j<=len; j++) 66 num[j] = num[j]*cycle[i]; 67 68 for(int j=0; j<=len; j++) { 69 num[j+1] += num[j]/10; 70 num[j] = num[j]%10; 71 } 72 while(num[len+1]) { 73 num[len+2]+=num[len+1]/10; 74 num[++len]%=10; 75 } 76 } 77 78 for(int i=len; i>=0; i--) 79 printf("%d",num[i]); 80 puts(""); 81 } 82 83 84 85 } sol; 86 87 int main() { 88 freopen("cactus.in","r",stdin); 89 freopen("cactus.out","w",stdout); 90 int n,m; 91 scanf("%d%d",&n,&m); 92 93 sol.init(n); 94 95 for(int i=0; i<m; i++) { 96 int k,u; 97 scanf("%d%d",&k,&u); 98 for(int i=0; i<k-1; i++) { 99 int v; 100 scanf("%d",&v); 101 sol.AddEdge(u,v); 102 u = v; 103 } 104 } 105 106 sol.dfs(1,-1); 107 108 sol.ans(); 109 110 //printf("%d\n",sol.ans()); 111 112 return 0; 113 }