有向图的强联通分量之:【求最长链】【求最长链的方案数(图论中的方案数DP)】【最长链和最大半联通子图 节点数相同】【最长链与最大半联通子图等价又不完全等价】
生活随笔
收集整理的這篇文章主要介紹了
有向图的强联通分量之:【求最长链】【求最长链的方案数(图论中的方案数DP)】【最长链和最大半联通子图 节点数相同】【最长链与最大半联通子图等价又不完全等价】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?注意了:
最長鏈與最大半聯通子圖是等價又不完全等價的。
最大半聯通子圖的節點數 會 與最長鏈的節點數相同,
但是邊數的話,最大半聯通子圖還是會加進 兩個點之間的所有邊
但是本題的主要目的是求 最長鏈上的節點數,所以不要緊
?
?
#include <bits/stdc++.h> using namespace std; const int N=1e5+10,M=2e6+10; typedef pair<int,int> PII; typedef long long LL; int n,m,mode; int e[M],ne[M],h[N],idx,hs[N]; int dfn[N],low[N],timestamp; int stk[N],top; int id[N],siz[N],scc_cnt; bool in_stk[N]; int f[N],g[N];void add(int h[],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;for(int i=h[u];i!=-1;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;siz[scc_cnt]++;}while(y!=u);} }int main() {memset(h,-1,sizeof h);memset(hs,-1,sizeof hs);scanf("%d%d%d",&n,&m,&mode);while(m--){int a,b;scanf("%d%d",&a,&b);add(h,a,b);}for(int i=1;i<=n;i++){if(!dfn[i]){tarjan(i);}}//通過縮點的過程,把強連通分量這個新圖(拓撲圖)建立起來/*判邊重,但是想一下,我們用什么來表示一個邊呢?(用邊上兩端點的 編號)來表示,由于編號的范圍在 1e5左右,所以我們可以用 u*1e6+v 來區分*/unordered_set<LL> s;for(int i=1;i<=n;i++)for(int j=h[i];j!=-1;j=ne[j]) //枚舉原圖{int k=e[j];int a=id[i],b=id[k];LL hash=(LL)a*1000000+b;if(a!=b&&!s.count(hash)){add(hs,a,b);s.insert(hash);}}//枚舉聯通塊,更新dp數組for(int i=scc_cnt;i;i--){if(!f[i]){f[i]=siz[i]; //f[i]是以第i個點為終點的節點數量最大值g[i]=1; //讓f[i]取得最大值的方案數}for(int j=hs[i];j!=-1;j=ne[j]){int k=e[j];if(f[k]<f[i]+siz[k]){f[k]=f[i]+siz[k];g[k]=g[i];}else if(f[k]==f[i]+siz[k]){g[k]=(g[k]+g[i])%mode;}}}int maxf=0,sum=0; //存最長值,和方案數for(int i=1;i<=scc_cnt;i++){if(f[i]>maxf){maxf=f[i];sum=g[i];}else if(f[i]==maxf){sum=(sum+g[i])%mode;}}printf("%d\n",maxf);printf("%d\n",sum);return 0; }總結
以上是生活随笔為你收集整理的有向图的强联通分量之:【求最长链】【求最长链的方案数(图论中的方案数DP)】【最长链和最大半联通子图 节点数相同】【最长链与最大半联通子图等价又不完全等价】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux中光盘使用的文件类型,Linu
- 下一篇: ICO泡沫破灭,是马甲的脱落,区块链技术