tarjan講解(用codevs1332(tarjan的裸題)講解)

来源:http://www.cnblogs.com/haizhe/archive/2016/09/16/5866549.html
-Advertisement-
Play Games

主要藉助這道比較裸的題來講一下tarjan這種演算法 tarjan是一種求解有向圖強連通分量的線性時間的演算法。(用dfs來實現) 如果兩個頂點可以相互通達,則稱兩個頂點強連通。如果有向圖G的每兩個頂點都強連通,稱G是一個強連通圖。有向圖的極大強連通子圖,稱為強連通分量。 在上面這張有向圖中1,2,3, ...


主要藉助這道比較裸的題來講一下tarjan這種演算法

 tarjan是一種求解有向圖強連通分量的線性時間的演算法。(用dfs來實現)

如果兩個頂點可以相互通達,則稱兩個頂點強連通。如果有向圖G的每兩個頂點都強連通,稱G是一個強連通圖。有向圖的極大強連通子圖,稱為強連通分量。

 

在上面這張有向圖中1,2,3,4形成了一個強連通分量,而1,2,4,和1,3,4並不是(因為它們並不是極大強連通子圖)。

tarjan是用dfs來實現的(用了tarjan後我們就可以對圖進行縮點(當然這道裸題用不到))

這道題只要找到最大的強連通分量,並且把將該強連通分量的序號從小到大輸出(如果有一樣大的強連通分量,那麼輸出含有更小的點的那一個)

下麵來道題:(tarjan代碼加註釋往下拉)

題目

題目描述 Description
      在幻想鄉,上白澤慧音是以知識淵博聞名的老師。春雪異變導致人間之里的很多道路都被大雪堵塞,使有的學生不能順利地到達慧音所在的村莊。因此慧音決定換一個能夠聚集最多人數的村莊作為新的教學地點。人間之里由N個村莊(編號為1..N)和M條道路組成,道路分為兩種一種為單向通行的,一種為雙向通行的,分別用1和2來標記。如果存在由村莊A到達村莊B的通路,那麼我們認為可以從村莊A到達村莊B,記為(A,B)。當(A,B)和(B,A)同時滿足時,我們認為A,B是絕對連通的,記為<A,B>。絕對連通區域是指一個村莊的集合,在這個集合中任意兩個村莊X,Y都滿足<X,Y>。現在你的任務是,找出最大的絕對連通區域,並將這個絕對連通區域的村莊按編號依次輸出。若存在兩個最大的,輸出字典序最小的,比如當存在1,3,4和2,5,6這兩個最大連通區域時,輸出的是1,3,4。 

輸入描述 Input Description
第1行:兩個正整數N,M

第2..M+1行:每行三個正整數a,b,t, t = 1表示存在從村莊a到b的單向道路,t = 2表示村莊a,b之間存在雙向通行的道路。保證每條道路只出現一次。

輸出描述 Output Description
第1行: 1個整數,表示最大的絕對連通區域包含的村莊個數。

第2行:若幹個整數,依次輸出最大的絕對連通區域所包含的村莊編號。

樣例輸入 Sample Input
5 5

1 2 1

1 3 2

2 4 2

5 1 2

3 5 1

樣例輸出 Sample Output
3

1 3 5

數據範圍及提示 Data Size & Hint
對於60%的數據:N <= 200且M <= 10,000

對於100%的數據:N <= 5,000且M <= 50,000
View Code

 很明顯這道題需要用到tarjan

#include<stdio.h>
#include<algorithm>
using namespace std;
int dfn[500000], low[500000], stack[900000], j, number, n, m, x, y, w, hh[600000], cnt, top, c, q, ans, yy[100000];
int color[400000], u, num, p[400000];
bool d[500000];
struct node
{
    int next, z, e;
} b[110000];
void add(int aa, int bb)//鄰接表
{
    b[++cnt].e = bb;
    b[cnt].next = hh[aa];
    hh[aa] = cnt;
}

 

tarjan代碼:

int tarjan(int k)
{
    int i;
    dfn[k] = low[k] = ++number;//dfn記錄的是訪問此節點的真實時間,low記錄的是
    stack[++top] = k;將當前點入棧
    d[k] = true;//這是表示點k的狀態
    for(i = hh[k]; i != 0; i = b[i].next)
    {
        if(!dfn[b[i].e])如果當前節點沒有訪問過就繼續搜
        {
            tarjan(b[i].e);
            low[k] = min(low[k], low[b[i].e]);
        }
        else if(d[b[i].e] == true)
        {
            low[k] = min(low[k], dfn[b[i].e]);
//當然也可以寫成low[k]=min(low[k],low[b[i].e]); } }
if(dfn[k] == low[k])//如果該點是強連通分量的根,也就是說我們已經找到了一個強連通分量,就開始彈棧 { color[k] = ++num;//把該強連通分量上的點全部染成同一種顏色 while(1) { p[num]++;//記錄該強連通分量上的點 d[stack[top]] = false;//棧頂元素出棧 color[stack[top--]] = num;將棧頂元素的顏色染成當前該強連通分量的顏色 if(stack[top + 1] == k)break;//因為根肯定是當前強連通分量上最先訪問,也就是最先入站的,所以彈出了根代表該強連通分量上的已全部彈出 } } return 0; }

 

int main()
{
    int i;
    scanf("%d %d", &n, &m);
    u = 1;
    for(i = 1; i <= m; i++)
    {
        scanf("%d %d %d", &x, &y, &w);
        if(w == 1)add(x, y);//建邊
        else
        {
            add(x, y);
            add(y, x);
        }
    }
    for(j = 1; j <= n; j++)
    {
        if(!dfn[j])tarjan(j);//如果當前點沒有被搜過,就從當前點進行深搜
    }
    for(i = 1; i <= n; i++)
    {
        if(p[color[i]] > ans)ans = p[color[i]], u = i;
    }
    printf("%d\n", ans);
    for(i = 1; i <= n; i++)
    {
        if(color[i] == color[u])printf("%d ", i);
    }
    return 0;
}

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 如:/application/uctenter/controller 如:/application/uctenter/controller/User.php class User{ //屬性 public userName; //駝峰命名首字母小寫 //私有屬性 private _userAge;  ...
  • Counter(計數器) 是一個字典的子類,存儲形式同樣為字典,其中存儲的鍵為字典的元素,值為元素出現的次數,在使用之前我們需要先導入文件 import collections 初始化一個計數器 most_common(self,n) 取出元素最多的前n項 sorted(c) 給計數器排序 ''.j ...
  • 由於Django是動態網站,所有每次請求均會去數據進行相應的操作,當程式訪問量大時,耗時必然會更加明顯,最簡單解決方式是使用:緩存,緩存將一個某個views的返回值保存至記憶體或者memcache中,5分鐘內再有人來訪問時,則不再去執行view中的操作,而是直接從記憶體或者Redis中之前緩存的內容拿到 ...
  • 利用django的Q()功能可以很好的展開搜索功能 假設我要做個這樣的搜索功能 那麼思路是怎麼樣的? 那我們就來看看代碼 前端的代碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title ...
  • 今天看到園友心白水撰寫的《簡單翻譯工具--必應字典第三方API使用方法》,感覺很不錯,所以用Python也寫了一個。源碼如下: 程式運行的結果如下: 請輸入英文單詞: python美音:[ 'paɪθɑn ] 英音:[ 'paɪθ(ə)n ] n. 蟒;蚺蛇Web 蟒蛇;巨蟒;派森 例句en: Se ...
  • 分類 分類可以模塊化方法的定義,可以用於向現有的類添加新的方法。 分類提供了一種簡單的方式,用他可以將類的定義模塊化到相關方法的組或分類中。它還提供了拓展現有類定義的簡便方式,並且不必訪問類的源代碼,也無需創建子類。 分類可以通過兩種方法來實現: 1.繼承自一個分類:可以通過將分類名稱括在類名稱之後 ...
  • 題目鏈接 http://vjudge.net/contest/132391#problem/G Description standard input/outputStatements — It' s a good game, — Princess said pensively. It was cle ...
  • 題目 輸入 第一行包含兩個整數N、M。N表示路口的個數,M表示道路條數。接下來M行,每行兩個整數,這兩個整數都在1到N之間,第i+1行的兩個整數表示第i條道路的起點和終點的路口編號。接下來N行,每行一個整數,按順序表示每個路口處的ATM機中的錢數。接下來一行包含兩個整數S、P,S表示市中心的編號,也 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...