強連通分量(學習心得)

定義:有向圖強連通分量:在有向圖G中,如果兩個頂點vi,vj間(vi>vj)有一條從vi到vj的有向路徑,同時還有一條從vj到vi的有向路徑,則稱兩個頂點強連通如果有向圖G的每兩個頂點都強連通,稱G是一個強連通圖。有向圖的極大強連通子圖,稱為強連通分量。

求強連通分量:

vector<int>pic[maxn];
int dfn[maxn],low[maxn],ans[maxn];
bool ins[maxn];
stack<int>st;
int dind=0,block=0;
int siz[maxn],cud[maxn];
void tarjan(int x)
{dind++;dfn[x]=low[x]=dind;ins[x]=true;st.push(x);for (int j=0;j<pic[x].size();j++){int y=pic[x][j];if (dfn[y]==0){tarjan(y);low[x]=min(low[x],low[y]);}else if (ins[y]) low[x]=min(low[x],dfn[y]);}if (low[x]==dfn[x]){block++;siz[block]=0;while (true){int thi=st.top();st.pop();ans[thi]=block;siz[block]++;ins[thi]=false;if (thi==x) break;}}
}

  例題1【UVA-11324 最大團】

分析:先計算強連通分量,然后建一張新圖,每個點的權值是它所包含的點的數量,求圖的最長鏈。

代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
using namespace std;
const int maxn=1010;
vector<int> pic[maxn],new_[maxn];
int dfn[maxn],low[maxn],ans[maxn];
bool ins[maxn];
stack<int>st;
int dind=0,block=0;
int siz[maxn],dp[maxn],Ans;
void tarjan(int x)
{dind++;dfn[x]=low[x]=dind;ins[x]=true;st.push(x);for (int j=0;j<pic[x].size();j++){int y=pic[x][j];if (!dfn[y]){tarjan(y);low[x]=min(low[x],low[y]);}else if (ins[y]) low[x]=min(low[x],dfn[y]);}if (low[x]==dfn[x]){block++;siz[block]=0;while (true){int thi=st.top();st.pop();ans[thi]=block;siz[block]++;ins[thi]=false;if (thi==x) break;}}
}
int DP(int x){    if(dp[x]!=-1) return dp[x];int Max=0;  for(int i=0;i<new_[x].size();i++)  Max=max(Max,DP(new_[x][i]));  return dp[x]=siz[x]+Max;
}
void init(int n){for(int i=1;i<=n;i++) pic[i].clear(),new_[i].clear();memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low));memset(ans,0,sizeof(ans)); memset(ins,0,sizeof(ins));while(!st.empty()) st.pop(); dind=block=Ans=0;memset(siz,0,sizeof(siz)); memset(dp,-1,sizeof(dp));
}
int main(){int n,m,N,u,v;scanf("%d",&N);while(N--){scanf("%d%d",&n,&m);init(n);while(m--){scanf("%d%d",&u,&v);pic[u].push_back(v);}for(int i=1;i<=n;i++)if(!dfn[i]) tarjan(i);for(int i=1;i<=n;i++)for(int j=0;j<pic[i].size();j++)if(ans[i]!=ans[pic[i][j]]) new_[ans[pic[i][j]]].push_back(ans[i]);for(int i=1;i<=block;i++) Ans=max(Ans,DP(i));printf("%d\n",Ans);}return 0;
}

  例題2【POJ 1236 學校網絡】

第一問:縮點后求入度為0的結點數量;

第二問:對于一張有向無環圖,可以通過把葉子結點連向根節點使它強連通;

like this:

所以需要連的邊數量為max(葉節點,根節點);

葉節點是出度為0的點,根節點是入度為0的點;

注意當只有一個強連通分量時,需要特判,為0;

代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<set>
using namespace std;
const int maxn=110;
vector<int> pic[maxn];
int dfn[maxn],low[maxn],ans[maxn];
bool ins[maxn];
stack<int>st;
set<int>check[maxn];
int dind=0,block=0;
int siz[maxn];
int ans1,in[maxn],out[maxn];void tarjan(int x)
{dind++;dfn[x]=low[x]=dind;ins[x]=true;st.push(x);for (int j=0;j<pic[x].size();j++){int y=pic[x][j];if (!dfn[y]){tarjan(y);low[x]=min(low[x],low[y]);}else if (ins[y]) low[x]=min(low[x],dfn[y]);}if (low[x]==dfn[x]){block++;siz[block]=0;while (true){int thi=st.top();st.pop();ans[thi]=block;siz[block]++;ins[thi]=false;if (thi==x) break;}}
}
int main(){int n,i,j;scanf("%d",&n);for(i=1;i<=n;i++){scanf("%d",&j);while(j) pic[i].push_back(j),scanf("%d",&j);	}for(int i=1;i<=n;i++)if(!dfn[i]) tarjan(i);for (i=1;i<=n;i++)for (j=0;j<pic[i].size();j++){int b1=ans[i],b2=ans[pic[i][j]];if (b1==b2) continue;if (check[b1].count(b2)) continue;check[b1].insert(b2);in[b2]++; out[b1]++;}int root=0,leaf=0;for(int i=1;i<=block;i++){if(!in[i]) root++;if(!out[i]) leaf++;}printf("%d\n",root);if(block==1) printf("0");else printf("%d",max(leaf,root));return 0;
}

  類似的還有【HDU 2767】

很奇怪的是提交時出現了這樣尷尬的問題:

0_0_20950778_21662.cpp
0_0_20950778_21662.cpp(29) : error C3861: “min”:? 找不到標識符
0_0_20950778_21662.cpp(31) : error C3861: “min”:? 找不到標識符
0_0_20950778_21662.cpp(83) : error C3861: “max”:? 找不到標識符

然后在出錯的庫后面加上了#include "minmax.h",就過了?(莫名其妙)

代碼:

#include<iostream>
#include "minmax.h" 
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<set>
using namespace std;
const int maxn=20010;
vector<int> pic[maxn];
int dfn[maxn],low[maxn],ans[maxn];
bool ins[maxn];
stack<int>st;
set<int>check[maxn];
int dind=0,block=0,siz[maxn];
int in[maxn],out[maxn],T;
void tarjan(int x)
{dind++;dfn[x]=low[x]=dind;ins[x]=true;st.push(x);for (int j=0;j<pic[x].size();j++){int y=pic[x][j];if (!dfn[y]){tarjan(y);low[x]=min(low[x],low[y]);}else if (ins[y]) low[x]=min(low[x],dfn[y]);}if (low[x]==dfn[x]){block++;siz[block]=0;while (true){int thi=st.top();st.pop();ans[thi]=block;siz[block]++;ins[thi]=false;if (thi==x) break;}}
}
void init(int n){for(int i=1;i<=n;i++)  pic[i].clear(),check[i].clear();;memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low));memset(ans,0,sizeof(ans)); memset(ins,0,sizeof(ins));while(!st.empty()) st.pop(); dind=0;block=0; memset(siz,0,sizeof(siz));memset(in,0,sizeof(in)); memset(out,0,sizeof(out));
}
int main(){scanf("%d",&T);while(T--){int n,i,j,m;scanf("%d%d",&n,&m);init(n);for(i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);pic[x].push_back(y);	}for(int i=1;i<=n;i++)if(!dfn[i]) tarjan(i);for (i=1;i<=n;i++)for (j=0;j<pic[i].size();j++){int b1=ans[i],b2=ans[pic[i][j]];if (b1==b2) continue;if (check[b1].count(b2)) continue;check[b1].insert(b2);in[b2]++; out[b1]++;}int root=0,leaf=0;for(int i=1;i<=block;i++){if(!in[i]) root++;if(!out[i]) leaf++;}if(block==1) printf("0\n");else printf("%d\n",max(leaf,root));}return 0;
}

  ————————————————————————————————————————————————————————

?來自Paper Cloud的博客,未經允許,請勿轉載,謝謝

轉載于:https://www.cnblogs.com/PaperCloud/p/7113385.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/258134.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/258134.shtml
英文地址,請注明出處:http://en.pswp.cn/news/258134.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java for的增強_Java基礎之增強for循環

平時大家for循環應該用的不少&#xff0c;特別是增強for循環&#xff0c;簡單快捷。但是在增強for中做刪除操作&#xff0c;卻會拋出java.util.ConcurrentModificationException&#xff0c;一起來看下。上面的代碼&#xff0c;在for循環執行完if中的remove&#xff0c;遍歷下一…

window.history 和 DWZ 框架

DWZ框架的ajax請求返回的一般都是一個HTML片段&#xff0c;整個頁面是由一個個HTML片段組成的&#xff0c;可以由TAB切換其內容&#xff0c;但是只有一個body和HEAD&#xff0c;一般head 和 菜單欄是不會動的。 今天遇到一個問題&#xff0c;當一個點擊進入一個tab頁面時&#…

大道至簡(第六章)讀后感

大道至簡&#xff08;第六章&#xff09;讀后感 還是不樂意去讀&#xff0c;但總算可以耐心的讀下去了&#xff0c;這也許也算是讀大道至簡以來的收獲之一吧。第六章的題目是從編程到工程&#xff0c;看到工程二字&#xff0c;讓我不由想起了前幾天和高中同學聊天。他報的燕大土…

遏止個人信息泄露亟待立法跟進

據報道&#xff0c;近日全國30個省份275位艾滋病感染者稱接到了詐騙電話&#xff0c;艾滋病感染者的個人信息疑似被大面積泄露。無獨有偶&#xff0c;近日票務網站大麥網因賬號信息被竊取&#xff0c;間接導致全國多地用戶受騙。目前至少有17名受害者&#xff0c;被騙至少54萬元…

確認類是否可以在運行期使用

問題: 你正在使用最新版的 SDK 中的一些類,但是你不確定這些類是否能在你程序運行的設 備中可用,因為有可能你部署的目標設備要比最新版 SDK 早。 方案: 用NSClassFromString函數. 傳入類的名稱字符串符。若是返回值為空(nil),則表示這個類無法在這臺設備上使用;反之,這個類則…

最新hosts,更新hosts,可用

點擊這里&#xff0c;全選后復制&#xff0c;粘貼到C:\Windows\System32\drivers\etc的hosts里面&#xff0c;把原來的置換了轉載于:https://www.cnblogs.com/zzw1994/p/4940924.html

酒店業解決方案

思科業務就緒酒店解決方案&#xff0c;為酒店的經營和管理提供一個高效率、高盈利、且可不斷發展和改進的平臺&#xff0c;幫您重建酒店競爭優勢&#xff0c;為酒店帶來意想不到的轉變&#xff01; 思科酒店行業解決方案更加融合的思科網絡在改善酒店的運營和員工生產率&#x…

配置SQL Server 2012 AlwaysOn ——step1 建立AD域及DNS配置

需要三臺安裝好windows server 2008 R2 sp1的虛擬機服務器SQLTESTDNS&#xff0c;SQLTESTMAIN,SQLTESTSUB&#xff0c;以SQLTESTMAIN為主數據庫及群集服務器&#xff0c;SQLTESTDNS為DNS及域服務器 1.在SQLTESTDNS的服務器管理器內設置靜態IP地址192.168.10.1,DNS為127.0.0.1&a…

lintcode:遞歸打印數字

題目 用遞歸打印數字 用遞歸的方法找到從1到最大的N位整數。 樣例 給出 N 1, 返回[1,2,3,4,5,6,7,8,9]. 給出 N 2, 返回[1,2,3,4,5,6,7,8,9,10,11,...,99]. 注意 用下面這種方式去遞歸其實很容易&#xff1a; recursion(i) {if i > largest number:returnresults.add(i)r…

做免費的EDM,EmailCar看中的是挖掘數據的價值

從2008年開始&#xff0c;做了9年企業級EDM&#xff08;電子郵件營銷&#xff09;服務的陸霏近日宣布&#xff0c;他們的產品EmailCar從4.0版本開始永久免費為企業提供電子郵件基礎投遞業務。 我們電子郵箱經常收到的推廣郵件就屬于EDM&#xff0c;即Email Direct Marketing。這…

java 讀取split_Java報錯系列——split

在String中,split方法如下&#xff1a;可見&#xff0c;split的核心在于Pattern.compile(regex).split(this, limit);Java提供Pattern,Matcher用于支持正則&#xff0c;可以看一個例子&#xff1a;運行結果是&#xff1a;0,1||3,4|ab|7,8|cef|8,9||11,12|kk|13,14|a|需要注意的…

VS2012生成事件

Visual Studio 事件生成功能對我們開發綜合項目的過程中尤為重要。 下面以VS2012為例&#xff1a; 選擇工程-> 屬性->編譯->生成事件 包括兩個生成事件&#xff1a;預先生成事件和后期生成事件 直接在相應的文本框里編寫寫腳本即可&#xff0c;如&#xff1a;編譯完成…

H3C Navigate 2017 | 拉近世界的距離 新華三的泛聯接版圖

就今天而言&#xff0c;聯接世界的網絡外延已經無限擴大&#xff0c;聯接的方式也越來越復雜。從互聯網時代的PC互聯&#xff0c;演進到移動互聯網時代手機等移動終端的互聯&#xff0c;而即將大規模爆發的物聯網應用時代&#xff0c;所有的事物都可能被連入網絡&#xff0c;一…

java gc log調優_Java 開啟 gc 日志

構建一個 jar 包程序使用 Spring Boot 構建一個簡單的 web 程序&#xff0c;可以直接使用 java -jar 來啟動。RestControllerRequestMapping("/root")SpringBootApplicationpublic class SbDemoApplication {public static void main(String[] args) {SpringApplicat…

大數據時代的公共安全治理

未來&#xff0c;大數據將成為社會基礎設施的一部分&#xff0c;跟公路、自來水、電一樣&#xff0c;成為人們生活不可或缺的一部分。但大數據的作用并不僅僅局限于為普通消費者提供生活必須服務&#xff0c;它已經開始在信息產業、公共安全、交通運輸、金融、水利等領域中發揮…

CCNA第二講筆記

網絡定義&#xff1a;一組由介質&#xff08;線纜&#xff09;互聯的網絡設備&#xff08;路由器、交換機&#xff09;和終端系統&#xff08;PC&#xff09;&#xff1b; 工作組&#xff1a;局域網范疇&#xff0c;范圍最小的局域網&#xff0c;且不涉及網絡設備。臺式機需要有…

晶科電力打造山東省最大物流港分布式光伏項目

近日&#xff0c;晶科電力有限公司宣布&#xff0c;由該公司投建的山東省最大物流港分布式光伏項目已破土動工&#xff0c;成為山東省又一標志性光伏項目。 該項目裝機量為6兆瓦&#xff0c;占用物流港廠房屋頂面積約68330平方米&#xff0c;平均每年發電量約601.22萬kWh&#…

服務器資源管理器視圖的添加顯示的步驟

MVC視圖查看數據庫表結構時&#xff0c;通常會打開服務器資源管理器視圖&#xff0c;在服務器資源管理器視圖中能查看表的數據集及表結構 打開的方法為&#xff1a; ①可使用快捷鍵&#xff1a; ctrlaltS ②也可添加“服務器資源管理器視圖”到“視圖”工具菜單&#xff0c;做法…

java中怎么用代碼打出ASCII碼字符_JAVA實現打印ascii碼表代碼

我就廢話不多說了&#xff0c;大家還是直接看代碼吧~package com.jalor;public class AAAA {public static void main(String[] args) {outputA(65);outputA(97);}// 打印ascii碼表public static void outputA(int count){for (int i 0; i < 26; i) {System.out.print((cha…

javascript this指針指向?

前言 理解javascript的指針就需要先了解js的執行環境和作用域&#xff01;執行環境的定義了變量或函數有權訪問的其他數據&#xff0c;決定了它們各自的行為。每個執行環境都有一個與之關聯的變量對象&#xff0c;環境中定義的所有的變量和函數都保存在這個對象中。雖然我們編寫…