UVA 11324强连通分量缩点+DAG上最长路(不明白算法为什么正确ing)

  1 /*UVA 11324强连通分量缩点+DAG上最长路(不明白算法为什么正确ing)
  2 主要是为了练习缩点和GAD
  3 */
  4 #include <stdio.h>
  5 #include <stdlib.h>
  6 #include <string.h>
  7 #include <math.h>
  8 #include <ctype.h>
  9 #include <string>
 10 #include <iostream>
 11 #include <sstream>
 12 #include <vector>
 13 #include <queue>
 14 #include <stack>
 15 #include <map>
 16 #include <list>
 17 #include <set>
 18 #include <algorithm>
 19 #define INF 0x3f3f3f3f
 20 #define LL long long
 21 #define eps 1e-7
 22 #define maxn 1100
 23 using namespace std;
 24 
 25 //scc_cnt是计数器
 26 //sccno[i]是i属于的分量
 27 //注意scc不像bcc,分量间是没有公共点的
 28 
 29 int t,n,m;
 30 
 31 int pre[maxn] ,sccno[maxn] , low[maxn], dfs_clock , scc_cnt;
 32 stack<int>S;
 33 vector<int>G[maxn] ,scc[maxn];
 34 void dfs(int u){
 35     low[u] = pre[u] = ++dfs_clock;
 36     S.push(u);
 37     int ecnt = G[u].size();
 38     for(int i=0;i<ecnt ; i++){
 39         int v = G[u][i];
 40         if(!pre[v]){
 41             dfs(v);
 42             low[u] = min(low[u] , low[v]);
 43         }
 44         else if(!sccno[v]){
 45             low[u] = min(low[u] , pre[v]);
 46         }
 47     }
 48     if(low[u] == pre[u]){
 49         scc[++scc_cnt].clear();
 50         while(true){
 51             int x = S.top(); S.pop();
 52             sccno[x] = scc_cnt;
 53             scc[scc_cnt].push_back(x);
 54             if(x == u) break;
 55         }
 56     }
 57 }
 58 void find_scc(int n){
 59     memset(pre ,0 ,sizeof(pre));
 60     memset(sccno ,0 ,sizeof(sccno));
 61     dfs_clock = scc_cnt = 0;
 62     for(int i=1;i<=n;i++){
 63         if(!pre[i]) dfs(i);
 64     }
 65 }
 66 
 67 bool G1[maxn][maxn];//新图的邻接矩阵,方便判断
 68 void BuiltNG()//建立缩点后的新的DAG图
 69 {
 70     memset(G1,0,sizeof(G1));
 71     for(int i=1;i<=n;i++)//枚举原先的每条边
 72     {
 73         for(int j=0;j<G[i].size();j++)
 74         {
 75             int u=sccno[i],v=sccno[G[i][j]];
 76             if (u!=v) G1[u][v]=true;
 77         }
 78     }
 79     return ;
 80 }
 81 int d[maxn];
 82 int dp(int u)//记忆化搜索求GAD上的最长路,很长时间没写了,需要复习啊
 83 {
 84     int &ans = d[u];
 85     if (ans!=-1) return ans;
 86     ans=0;
 87     for(int i=1;i<=scc_cnt;i++)
 88     {
 89         if (G1[u][i]) ans=max(ans,dp(i));
 90     }
 91     ans+=scc[u].size();
 92     return ans;
 93 }
 94 int solve()
 95 {
 96     int mx=0;
 97     memset(d,-1,sizeof(d));
 98     for(int i=1;i<=scc_cnt;i++)
 99     {
100         mx=max(mx,dp(i));
101     }
102     return mx;
103 }
104 int main()
105 {
106     cin>>t;
107     while(t--)
108     {
109         cin>>n>>m;
110         for(int i=1;i<=n;i++) G[i].clear();
111         for(int i=1;i<=m;i++)
112         {
113             int u,v;
114             cin>>u>>v;
115             G[u].push_back(v);
116         }
117         find_scc(n);
118         BuiltNG();
119         cout<<solve()<<endl;
120 
121     }
122 }
原文地址:https://www.cnblogs.com/little-w/p/3574592.html