由於本人的文化課炸掉了,所以說從此用心開始學計算機,再也不插科打諢了。
在乙個有向聯通圖中,如果說有若干個點之間成乙個環(即任意兩點之間可以互相到達),那麼我們稱這些點為乙個強連通分量,下文統一用 \(scc\) 來表示。
在對圖論問題的分析中,其可以進行縮點,割邊等優秀操作來節省操作難度。
luogu p3387
對於乙個有向無權圖,如果說多個點成了乙個環,那麼我們的操作就開始十分的複雜了,所以說我們需要用強連通分量演算法 tarjan 來優化我們的演算法。
對於 tarjan 這個位老哥我不做多的介紹,感興趣的可以上網搜一搜他的個人簡介。
步入正題
tarjan 演算法的主要思想在於找乙個環,如果說找到了環,那麼就一定可以確定這幾個點是乙個強連通分量。
那麼怎麼找環和怎麼將乙個環縮成乙個點就成了我們需要注意的最大問題。
此時我們引入乙個概念:時間戳。
用兩個變數來定義時間戳。
\(dfn\) : 表示這個點是第幾個被訪問到的。
\(low\) : 表示這個點目前所在的強連通分量中能夠到達的最上面的時間戳。
有了以上兩個概念我們就可以開始寫強連通分量了(bushi)。
其實我們還需要思考乙個問題,如何將這些點真正的縮成乙個點。既然都說了是縮成乙個點,那麼我們建立乙個點不就完事了嗎。
下面的講解以及**中將會用 \(scc\) 來表示我所建立的點。
我們考慮將已經便利過的點存在乙個棧中,在回溯的時候我們只需要不斷地彈棧這樣就可以做到縮點了。
以上步驟全都包含在下列**中,如果說有什麼不懂的話,我建議去看這位大佬的報告,寫的十分詳細和有趣。
#include#include#include#includeusing namespace std;
const int maxn = 1e4+1;
vectore[maxn],e2[maxn];
int stk[maxn],tp,dfn[maxn],low[maxn],ccnt,scc[maxn],cnt,w1[maxn],w2[maxn],n,m,ans;
bool vis[maxn];
int f[maxn];
void tarjan(const int o) else if(vis[x])
} if(dfn[o] == low[o])
} return ;
}int dfs(const int x)
return f[x] += w2[x];
}int main()
} }memset(vis,0,sizeof(vis));
for(int i = 1; i <= n; i++)
printf("%d\n",ans);
return 0;
}
演算法 強連通分量縮點
有時對於乙個有向圖我們及其渴望將其變為乙個有向無環圖,這樣我們就要用到強連通分量縮點了。洛谷3387 縮點 題目背景 縮點 dp。題目描述 給定乙個 n個點 m條邊有向圖,每個點有乙個權值,求一條路徑,使路徑經過的點權值之和最大。你只需要求出這個權值和。允許多次經過一條邊或者乙個點,但是,重複經過的...
強連通分量縮點的模板
include include include include using namespace std define inti a memset a,0,sizeof a define min a,b a b b a define max a,b a b a b const int max 1605...
演算法學習之路 強連通分量 縮點
本來寒假是安排的很充實的,放假了一回到家就 演算法想想還是不能丟,雖然離acm銅牌的水平還差好遠,但是,不想留下遺憾,演算法慢慢的要重新拾起來的,雖然以前水平也不咋地 題目大意 一張有向圖,問至少再新增幾條有向邊,才能使它成為強連通圖。主要寫一下本題大致用到了哪些方面的知識,理一下思路。強連通分量 ...