【转】Cactus 仙人掌图 有向&无向
来源:互联网 发布:北大青鸟消防主机编程 编辑:程序博客网 时间:2024/05/22 11:54
转自:http://blog.csdn.net/kksleric/article/details/7870398
有向Cactus图:
1.它是一个强连通图。
2.它的任意一条边都属于且仅属于一个环。
有向Cactus图判定:
性质1 有向Cactus的DFS树没有横向边(不等价于非父子边)。
性质2 low(u)<=dfn(v) (u是v的儿子)
性质3 设某个点v有a(v)个儿子的low值小于dfn(v),同时v自己有b(v)条逆向边。那么a(v)+b(v)<2。
这三条性质也就是一个有向图是有向Cactus的充要条件。详细的证明请看《cactus solution》写的很详细,三个条件都有。
对应的题目HDU 3594,只要搞懂了定理很好实现,通过此题深刻理解了横叉边和反向边的区别。
无向Cactus图定义:
1.它是一个连通图。
2.它的任意一条边都至多属于一个环。
poj 2793 Cactus
题意:判断一个图是否为cactus图,并求计算一个图的cactus度:有多少个生成子图(包括自身)也是cactus。
解法:根据无向仙人掌图的定义,只需判断每条边属于几个环即可,对图进行dfs后所有父子边形成以棵树,每条反向边<a,b>加入树后都会使a-lca[a][b]--b形成一个环,可以用poj3417的做法(详见《Tarjan离线算法求LCA小结》)统计每条边被环覆盖了多少次。还有一种方法是在dfs时顺便维护,实现起来可能还会更简单些。
在确定是cactus图后只需统计每个环上有多少条边,然后利用乘法原理就可以计算度数.由于每条反向边只会形成一个环,因此记录每个节点的深度depth[],在碰到反向边<b,a>时,depth[b]-depth[a]+1就是这个环内边的条数,累乘即可,注意要用高精。
//无向cactus//POJ 2793#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <cstdlib>#include <cmath>#include <queue>#include <vector>#include <map>#define pb push_back#define mp make_pair#define eps 1e-9#define zero(x) (fabs(x)<eps)#define pi acos(-1.0)#define f1 first#define f2 second#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1#define initial 1,n,1const int inf=0x3f3f3f3f;const long long INF=1LL<<50;using namespace std;typedef long long LL;typedef pair <int, int> PII;template<typename X> inline bool minimize(X&p,X q){if(p<=q)return 0;p=q;return 1;}template<typename X> inline bool maximize(X&p,X q){if(p>=q)return 0;p=q;return 1;}#define N 20005#define M 70010const int L = 2000;const int B = 10000;struct BigInteger { BigInteger(int number = 0) : length(1) { memset(digit, 0, sizeof(digit)); digit[0] = number; } void init(int number) { length=1;digit[0] = number%B; if(number/B) { length++; digit[1]=number/B; } } void normalize() { while (length && !digit[length - 1]) { length --; } } BigInteger operator=(const BigInteger&oth){ length=oth.length; for (int i=0;i<length;i++) digit[i]=oth.digit[i]; return *this; } int length, digit[L];};void mul_(const BigInteger &a, const BigInteger &b,BigInteger &c){ memset(c.digit, 0, sizeof(int)*c.length); c.length = a.length + b.length; for (int i = 0; i < a.length; ++ i) { for (int j = 0, delta = 0; j <= b.length; ++ j) { delta += a.digit[i] * b.digit[j] + c.digit[i + j]; c.digit[i + j] = delta % B; delta /= B; } } c.normalize();}struct edge{ int from,to; edge(int a=0,int b=0):from(a),to(b){}};vector<int > g[N],rr;vector<edge> ed;BigInteger ans,ttt,tmp;bool vis[N],pp[N],ok[M];bool isc;int hea,scc,tim;int fa[N];int n,m;void add(int x,int y){ ed.pb(edge(x,y)); ed.pb(edge(y,x)); int m=ed.size(); g[x].pb(m-2); g[y].pb(m-1);}void dfss(int now,int from=-1){ vis[now]=1; for (int i=0,v;i<g[now].size();++i)if (!ok[g[now][i]]) { v=ed[g[now][i]].to; if (v==from) continue; if (vis[v]) {ok[g[now][i]^1]=1; int t=now; int tt=2; while (t!=v) { if (pp[t]) {isc=0; if (!isc) return;} pp[t]=1; tt++; t=fa[t]; } if (tt>3) rr.pb(tt); } else {fa[v]=now; dfss(v,now); if (!isc) return ; } }}void doit(){ for (int i=1;i<=n;i++) g[i].clear(); ed.clear(); for (int i=1,y,x,z;i<=m;i++) { scanf("%d",&y); scanf("%d",&z); for (int i=1;i<=y-1;i++) { scanf("%d",&x); if (ed.size()<M-10)add(x,z); z=x; } } if (ed.size()>=M-10){printf("0\n"); return;} memset(vis,0,sizeof(vis)); memset(fa,0,sizeof(fa)); memset(pp,0,sizeof(pp)); memset(ok,0,sizeof(ok)); isc=1;rr.clear(); for (int i=1;i<=n;i++) if (!vis[i]) {dfss(i,-1);break;} if(!isc) {printf("0\n"); return;} for (int i=1;i<=n;i++) if (!vis[i]) {printf("0\n"); return;} ans=1; for (int i=0;i<rr.size();i++) { ttt.init(rr[i]); if (i%2==0) mul_(ans,ttt,tmp); else mul_(tmp,ttt,ans); } if (rr.size()%2==1) ans=tmp; printf("%d", ans.digit[ans.length - 1]); for (int i = ans.length - 2; i >= 0; -- i) { printf("%04d", ans.digit[i]); } puts("");}int main(){ while (scanf("%d%d",&n,&m)!=EOF) doit();}
- 【转】Cactus 仙人掌图 有向&无向
- poj 2793 Cactus(无向仙人掌图判定)
- UVA 10510 - Cactus(有向仙人掌图判定)
- hdoj 3594 Cactus 【仙人掌图的判定】【有向图tarjan求SCC】
- 有向图和无向图
- bzoj1023 cactus仙人掌图
- 邻接表-建立无向图、无向网、有向图、有向网
- 有向图、有向网、无向图、无向网
- 【Cactus仙人掌图】仙人掌基础知识学习笔记
- 【Cactus仙人掌图】仙人掌DP学习笔记
- 有向图与无向图判断有环
- HDU - 3594 Cactus(仙人掌图)
- 【SHOI2008】【BZOJ1023】cactus仙人掌图
- 【bzoj1023】[SHOI2008]cactus仙人掌图
- 1023: [SHOI2008]cactus仙人掌图
- bzoj1023: [SHOI2008]cactus仙人掌图
- BZOJ1023 [SHOI2008]cactus仙人掌图
- HDOJ3594-Cactus(仙人掌图)
- 并查集——电影投票
- 程序员生存定律--成长路上常见的坑(2)
- 线性规划与网络流24题の2 太空飞行计划问题(最大权闭合图问题)
- 根据指定端口探测服务器/模块部署python版本
- 如何使用google
- 【转】Cactus 仙人掌图 有向&无向
- 合并多行查询数据到一行:使用自连接、FOR XML PATH('')、STUFF或REPLACE函数
- 并查集——四六级1
- Buffer cache学习(二)
- PowerShell 调用 Oracle.ManagedDataAccess.dll
- [进阶]MySQL学习笔记六之Limit/Like/Wildcards
- "Real World OCaml" Installation Instructions
- IBM_V7000底层结构及数据恢复案例详解
- 信念、思考、行动-谈谈程序员返回家乡的创业问题