UVa 11324 最大团(强连通分量缩点)

https://vjudge.net/problem/UVA-11324

题意:
给一张有向图G,求一个结点数最大的结点集,使得该结点集中任意两个结点u和v满足,要么u可以到达v,要么v可以达到u。

思路:

找到SCC后进行缩点建图,每个点的权值则为其连通分量的点数,这样就是找DAG上一条最大路径,DP解决。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<vector>
  6 #include<stack>
  7 #include<queue>
  8 #include<cmath>
  9 using namespace std;
 10 
 11 const int maxn=1000+5;
 12 
 13 int n,m;
 14 
 15 vector<int> G[maxn];
 16 int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;
 17 int num[maxn];
 18 int map[maxn][maxn];
 19 int d[maxn];
 20 stack<int> S;
 21 
 22 void dfs(int u)
 23 {
 24     pre[u]=lowlink[u]=++dfs_clock;
 25     S.push(u);
 26     for(int i=0;i<G[u].size();i++)
 27     {
 28         int v=G[u][i];
 29         if(!pre[v])
 30         {
 31             dfs(v);
 32             lowlink[u]=min(lowlink[u],lowlink[v]);
 33         }
 34         else if(!sccno[v])
 35         {
 36             lowlink[u]=min(lowlink[u],pre[v]);
 37         }
 38     }
 39     if(lowlink[u]==pre[u])
 40     {
 41         scc_cnt++;
 42         for(;;)
 43         {
 44             int x=S.top(); S.pop();
 45             sccno[x]=scc_cnt;
 46             if(x==u)  break;
 47         }
 48     }
 49 }
 50 
 51 void find_scc()
 52 {
 53     dfs_clock=scc_cnt=0;
 54     memset(sccno,0,sizeof(sccno));
 55     memset(pre,0,sizeof(pre));
 56     for(int i=0;i<n;i++)
 57         if(!pre[i])  dfs(i);
 58 }
 59 
 60 int dp(int u)
 61 {
 62     int& ans=d[u];
 63     if(ans!=-1)   return ans;
 64     ans=num[u];
 65     for(int i=1;i<=scc_cnt;i++)
 66     {
 67         if(i!=u && map[u][i])   ans=max(ans,num[u]+dp(i));
 68     }
 69     return ans;
 70 }
 71 
 72 int main()
 73 {
 74     //freopen("D:\input.txt","r",stdin);
 75     int T;
 76     scanf("%d",&T);
 77     while(T--)
 78     {
 79         scanf("%d%d",&n,&m);
 80         for(int i=0;i<n;i++)  G[i].clear();
 81         while(m--)
 82         {
 83             int u,v;
 84             scanf("%d%d",&u,&v);
 85             u--; v--;
 86             G[u].push_back(v);
 87         }
 88         find_scc();
 89         memset(num,0,sizeof(num));
 90         memset(map,0,sizeof(map));
 91         for(int i=0;i<n;i++)
 92             num[sccno[i]]++;
 93         for(int u=0;u<n;u++)
 94         {
 95             for(int i=0;i<G[u].size();i++)
 96             {
 97                 int x=sccno[u];
 98                 int y=sccno[G[u][i]];
 99                 map[x][y]=1;
100             }
101         }
102         int ans=0;
103         memset(d,-1,sizeof(d));
104         for(int i=1;i<=scc_cnt;i++)
105             ans=max(ans,dp(i));
106         printf("%d
",ans);
107     }
108     return 0;
109 }
原文地址:https://www.cnblogs.com/zyb993963526/p/6798234.html