日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法提高课-图论-有向图的强连通分量-AcWing 1174. 受欢迎的牛:tarjan算法求强连通分量、tarjan算法板子、强连通图

發布時間:2025/4/5 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法提高课-图论-有向图的强连通分量-AcWing 1174. 受欢迎的牛:tarjan算法求强连通分量、tarjan算法板子、强连通图 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

      • 題目解答
      • 題目來源

題目解答


來源:acwing

分析:

強連通圖:給定一張有向圖。若對于圖中任意兩個結點x,y,既存在從x到y的路徑,也存在從y到x的路徑,則稱該有向圖是“強連通圖”。

強連通分量(SCC)指的是強連通圖的極大連通子圖(點最多的)。

說人話,強連通分量中任意兩點都存在邊再加入任何別的點,它都不再是連通分量。

或者說,對于一張有向圖,強連通分量就是任意兩點都有路徑(x能到y, y也能到x),并且包含點最多的圖。

有向圖的強連通分量有什么用呢?

主要是通過縮點(將強連通分量縮成一個點),把有向圖,轉換為有向無環圖(拓撲圖,DAG)。

如下圖,左圖圈內的是一個強連通分量,通過縮點,轉化為右圖。這種做法其實有很多應用,比如求最短路等。

需要知道的幾個概念:

  • 樹枝邊(x,y)
    x是y的父節點,x到y的邊稱為樹枝邊
  • 前向邊(x,y)
    x是y的祖先節點,x到y的邊稱為前向邊。
    樹枝邊是特殊的前向邊。
  • 后向邊(y,x)
    x是y的祖先節點,y到x的邊稱為后向邊。
  • 橫叉邊(x,y)
    在對有向圖進行dfs遍歷時,x是已經搜過的圖的分支(不是前向邊),現在在搜的點是y,y到x的有向邊是橫叉邊。
  • tarjin算法求強連通分量

    引入時間戳的概念:在dfs遍歷的過程中,按照每個結點第一次被訪問的時間順序,依次給予圖中N個結點1~N的整數標記,該標記被稱為時間戳,記為dfn[x].

    對每個點定義兩個時間戳:
    dfn[u]表示遍歷到u的時間戳;

    low[u] 表示從u開始走(遍歷它的子樹),所能遍歷到的最小時間戳是什么。

    我們在求強連通分量的時候,求的是每個強連通分量最上面的那個點。

    u是所在的強連通分量的最高點,等價于dfn[u]== low[u],因為low[u]表示的是從u開始能夠遍歷到的最小的時間戳,正好等于自己的時間戳,說明什么? 說明u就是這個連通分量的最高點啊!

    tarjan算法求強連通分量的模板

    背模板的思路

    /* 1. 加時間戳; 2. 放入棧中,做好標記; 3. 遍歷鄰點1)如果沒遍歷過,tarjan一遍,用low[j]更新最小值low2) 如果在棧中,用dfn[j]更新最小值low 4.找到最高點1)scc個數++2)do-while循環:從棧中取出每個元素;標志為出棧;對元素做好屬于哪個scc;該scc中點的數量++ */

    具體模板代碼

    // tarjan 算法求強連通分量 // 時間復雜度O(n+ m) void tarjan(int u){// 初始化自己的時間戳dfn[u] = low[u] = ++ timestamp;//將該點放入棧中stk[++ top] = u, in_stk[u] = true;// 遍歷和u連通的點for(int i = h[u]; ~i; i = ne[i]){int j = e[i];if(!dfn[j]){tarjan(j);// 更新u所能遍歷到的時間戳的最小值low[u] = min(low[u], low[j]);}// 如果當前點在棧中//注意棧中存的可能是樹中幾個不同分支的點,因為有橫叉邊存在// 棧中存的所有點,是還沒搜完的點,同時都不是強連通分量的最高點// 這里表示當前強連通分量還沒有遍歷完,即棧中有值else if(in_stk[j])//更新一下u點所能到的最小的時間戳//此時j要么是u的祖先,要么是橫叉邊的點,時間戳小于ulow[u] = min(low[u], dfn[j]);}// 找到該連通分量的最高點if(dfn[u] == low[u]){int y;++ scc_cnt; // 強連通分量的個數++do{// 取出來該連通分量的所有點y = stk[top --];in_stk[y] = false;id[y] = scc_cnt; // 標記點屬于哪個連通分量size_scc[scc_cnt] ++;} while(y != u);} }

    對于本題的解析:

    題意是找到被其他所有牛都歡迎的牛的數量。在有向圖的角度,就是所有的點都可以走到當前這個點。

    如果暴力做的話,對于每個點都要dfs或者bfs,看是否所有點都可以到達該點,做一遍的時間復雜度是O(n + m),那么n個點,時間復雜度是O(n(n+m)),這里的n是1w,m是5
    w,時間限制是1s,會超時。

    優化的解法:

    如果是拓撲圖(有向無環圖)的話,就好解決了。為什么呢?只需要統計出度為0的點的數量。如果出度為0的點的數量大于等于2,那么一定不存在最受歡迎的牛(其他所有點都有邊連到該點)。
    這是因為是有向無環圖,如果有2個或以上的點出度為0,那么其中1個葉子結點必然有到不了的點,也就是不存在最受歡迎的牛。這個需要畫圖理解一下。

    如果只存在一個出度為0的點呢?

    綜上,如果是拓撲圖的話,這道題就好做了。實際上,我們可以用強連通分量算法將圖轉換為拓撲圖!

    先求出該圖的強連通分量,然后縮點,變成有向無環圖。找到出度為0的點的數量為1的情況,然后統計該點所表示的強連通分量,其中包含多少個點,這里的所有點都可以被其他所有點走到。

    ac代碼

    #include<bits/stdc++.h> using namespace std;const int N = 10010, M = 50010;int n, m; int h[N], w[M], e[M], ne[M], idx; // 鄰接表一套 // dfn[u] 存的是遍歷到u的時間戳 // low[u]存的是從u出發,遍歷子樹,所能遍歷到的最小的時間戳 //timestamp 就是時間戳 int dfn[N], low[N], timestamp; int stk[N], top; // 棧,和棧頂元素索引 bool in_stk[N]; // 是否在棧中 //id[u]表示u的強連通分量的編號,scc_cnt表示強連通分量的編號 // size_scc[u]表示編號為u強連通分量中點的數量 int id[N], scc_cnt, size_scc[N]; int dout[N];// 記錄新圖中每個點(也就是原圖每個連通分量)的出度void add(int a, int b){e[idx] = b, ne[idx] = h[a], h[a] = idx ++; }void tarjan(int u){//當前點的時間戳dfn[u] = low[u] = ++ timestamp;// 加入棧中stk[++ top] = u, in_stk[u] = true;//遍歷u點的所有鄰點for(int i = h[u]; ~i; i = ne[i]){int j = e[i];if(!dfn[j]){//如果沒有遍歷過tarjan(j); // 遍歷它low[u] = min(low[u], low[j]);}// 當前點在棧當中else if(in_stk[j]) low[u] = min(low[u], dfn[j]);}if(dfn[u] == low[u]){++ scc_cnt; // 更新強連通分量的編號int y;do{y = stk[ top--]; //不斷取出棧內元素in_stk[y] = false;id[y] = scc_cnt; //y元素所屬的連通塊編號size_scc[scc_cnt] ++; //該連通塊內包含的點數}while(y != u); // 直到y不等于u}}int main(){cin >> n >> m;memset(h, -1, sizeof h);while(m --){int a, b;cin >> a >> b;add(a, b);}for(int i = 1; i <= n; i ++){if(!dfn[i])tarjan(i);}// 建有向無環圖// 統計在新圖中所有點的出度for(int i = 1; i <= n; i ++){for(int j = h[i]; ~j; j = ne[j]){int k = e[j];int a = id[i]; //a表示i所在連通分量的編號int b = id[k]; // b表示k所在連通分量的編號//如果點i和點k不在同一個連通塊// dout存的是出度,因為本題只需要出度//在其他題目中,可能是要建邊,因為這里是構造有向無環圖if(a != b) dout[a] ++; // 從a走到b,a的出度++}}// 和本題有關的部分:// zeros是統計在新圖中,出度為0的點的個數// sum表示滿足條件的點(最受歡迎的奶牛)的個數int zeros = 0, sum = 0;for(int i = 1; i <= scc_cnt; i ++){if(!dout[i]){zeros ++;sum += size_scc[i];if(zeros > 1){sum = 0;break;}}}cout << sum << endl; }

    題目來源

    https://www.acwing.com/problem/content/1176/

    總結

    以上是生活随笔為你收集整理的算法提高课-图论-有向图的强连通分量-AcWing 1174. 受欢迎的牛:tarjan算法求强连通分量、tarjan算法板子、强连通图的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 日韩国产激情 | 亚洲一区免费视频 | 夜夜激情| 国产精品久久久久久免费免熟 | 岛国av一区| 性色视频| 国产精品一区二区自拍 | 亚洲蜜桃av | www国产黄色 | 很污很黄的网站 | 国产一级片中文字幕 | 大乳丰满人妻中文字幕日本 | 色呦呦网| 亚洲av无码久久精品狠狠爱浪潮 | 日本一区二区三区久久 | 麻豆视频在线观看免费 | 日韩精品极品视频在线观看免费 | 天堂精品一区二区三区 | 人与动物2免费观看完整版电影高清 | 亚洲激情一区二区 | 亚洲第一页中文字幕 | a毛片网站| 拍摄av现场失控高潮数次 | 97中文字幕 | 一级大片在线观看 | 婷婷人体 | 日本无遮羞调教打屁股网站 | 求欧美精品网址 | 夜夜操网址 | 在线日韩成人 | 无码 制服 丝袜 国产 另类 | 青青草成人网 | 我的丝袜美腿尤物麻麻 | 国产玖玖 | 亚洲一区二区高清视频 | 国产涩涩| 我的丝袜美腿尤物麻麻 | 草草草在线视频 | 免费一二三区 | 国产亚洲av在线 | 致命魔术电影高清在线观看 | 国产一级生活片 | 91蜜桃在线| 亚洲深夜av | 日韩在线精品视频一区二区涩爱 | 国内av片 | 男女激情视频网站 | 中文字幕av一区二区三区人妻少妇 | 欧美性猛交 | 亚洲剧情在线 | 日日摸日日操 | 一本色道久久综合亚洲精品小说 | 一卡二卡三卡在线观看 | 美女18毛片 | 爆操少妇 | 欧美精品在线播放 | www.久久伊人 | a级片免费播放 | www.色99| 国产乱码一区二区三区播放 | 一区二区三区欧美视频 | 欧美成人自拍视频 | 黄色免费看片 | 亚洲第一视频在线播放 | 色老头一区二区三区在线观看 | 色婷婷免费| 91一区二区三区在线观看 | www.99精品| www.成人免费 | 久久这里只有精品6 | 又黄又爽又色视频 | 亚洲日本韩国在线 | 精品视频91| 97精品久久久 | 少妇精品视频 | 亚洲一区黄色 | av黄色片 | 国产稀缺精品盗摄盗拍 | 亚洲日本va中文字幕 | 影音先锋国产资源 | 五月天av在线 | 亚洲欧美日韩在线 | 欧美精品乱码视频一二专区 | 狠狠爱av| 亚州av片| 热热热热色| 日韩日b视频 | 在线视频一区二区三区四区 | 日韩精品三级 | 亚洲少妇中文字幕 | 成人免费毛片日本片视频 | 青青草狠狠干 | 东北老女人av | 女人和拘做爰正片视频 | 欧美又粗又长又爽做受 | 亚洲精品乱码久久久久久黑人 | 日本在线播放一区 | 韩国三色电费2024免费吗怎么看 | 欧美日韩久久久久 |