乙個有向圖稱為半連通(semi-connected),滿足:對於圖中任兩點u,v,存在一條u到v的有向路徑或者從v到u的有向路徑。 若滿足,則稱g』是g的乙個匯出子圖。
若g』是g的匯出子圖,且g』半連通,則稱g』為g的半連通子圖。若g』是g所有半連通子圖中包含節點數最多的,則稱g』是g的最大半連通子圖。
判斷乙個圖是不是半連通圖
求解:<1>kosarsju演算法: [1] 新圖dfs [2] 方法2
<2>tarjan演算法:[1] 新圖dfs
新圖dfs
void init_judge(void)
root=0;
is_halfscc=0;
}void judge_halfscc(int u,int depth)
ptr=ptr->next;
} }}
init_judge(); //half_scc判定 【主函式程式段】
for(int cn=1;cn<=num_scc;cn++)
if(in_d[cn] == 0)
root = cn; //找到入度為0的點,做起點dfs
vis_scc[root]=1;
judge_halfscc(root,1);
if(is_halfscc) printf("yes\n");
else printf("no\n");
方法2(僅適應於kosaraju演算法)
求出縮點後所有頂點的入度ind。思考:如果原圖g要是半連通的,那麼縮點後的圖mat必須要連通,這是基礎的前提,不然原圖都是不連通的,這時只要判斷mat中頂點是否只有乙個入度為0的點,如果當前的 dag 有不止乙個入度為 0 的點,那麼這些點之間是不可到達的,導致圖g不是半連通的。此外,mat就是一棵樹,入度為0的頂點就是根,如果這個樹不是一條鏈,那麼圖g也不是半連通的,不是鏈就說明有分叉,兩個分叉之間是不能到達的,那麼如何判斷是否有分叉呢?答案是拓撲排序,如果排序到某個節點後,剩下的順序不能確定,就說明出現了分叉。
其實程式是判斷樹的高度是否==num_scc。
void judge_half_scc(void)
if(num_indegree_0 > 1) //優先判斷重構圖是否連通
printf("no\n");
else
if(num_indegree_0>1 || num_indegree_0==0)
break;
in_degree[root]=-1; //標記+下層遍歷
depth++;
ptr=rebuild_alg->vlist[root].firstedge;
while(ptr!=null)
}if(depth==num_scc) //若相等
printf("yes\n");
else printf("no\n");
}}
求出有向圖的最大半連通子圖
tarjan或kosarju
縮點之後變為
dag,最大節點數即為
「最長鏈
」,一條鏈的長度定義為所有節點的權值之和,每個
scc的權值為它的節點個數。乙個注意的地方就是
tarjan
之後重構圖的時候會加入重邊,要消除重邊影響。乙個scc裡所有點之間都是半連通的。如果兩個強連通之間有邊,那麼這兩個強連通中的任意點也是半連通的。
[1].
找出入度為
0的點做
dfs,並統計
count權值
[2].count
是把父親節點的
num向孩子節點加;
[3].
找出count
陣列中的最大值
max_count
即可;
[4].
計算出與
max_count
相等的個數,即
max_halfscc
個數 在程式中,首先要記錄下每個scc包含的頂點個數num[i]。
/*深度優先搜尋尋找最大權值*/
void init_find(void)
root=0;
}void find_max_halfscc(int u)
ptr=ptr->next;
}}
init_find();
for(int cnt=1;cnt<=num_scc;cnt++) //【3.判定】
if(in_degree[cnt] == 0)
然後再執行第[3][4]步即可。至於求解最大半連通子圖中的頂點,只要對新圖的逆表作dfs即可。
void dfs_reverse_rebuild_alg(int u)
ptr=ptr->next;
}}
memset(vis_scc,0,sizeof(vis_scc));
for(int ii=1;ii<=num_scc;ii++) //對新圖的逆表做一次dfs
printf("\n");
}
BFS 連通分量 求連通分量
題目描述 求乙個圖的連通分量 input n 頂點數 100 邊 以0 0作為結束標誌 output 連通分量 強連通圖的連通分量為其本身。如果為非連通圖,則連通分量為該圖的最大連通子圖。分析 建乙個100 100的布林矩陣,b x,y true表示x與y連通。同時還要記錄該點是否被遍歷過 然後遍歷...
點連通分量 邊連通分量 割點和橋 強連通分量
老是搞不清他們的關係,不知道該用那份 今天理了一下,整理一下模板 點連通分量 可以求出點連通分量包含哪些點,那個點屬於那個連通分量 struct edge int pre maxn iscut maxn bccno maxn dfs clock,bcc cnt vectorg maxn bcc ma...
強連通分量 tarjan求強連通分量
雙dfs方法就是正dfs掃一遍,然後將邊反向dfs掃一遍。挑戰程式設計 上有說明。雙dfs 1 include 2 include 3 include 4 include 5 6using namespace std 7const int maxn 1e4 5 8 vector g maxn 圖的鄰...