UVA 11324 The Largest Clique(缩点+DAG上的dp)

求最大团。和等价性证明有类似之处,只不过这个不是求互推,而是只要a->b,或b->a即可。

同样的,容易想到先缩点,得到DAG,每个节点上保存SCC的点数,相信任意一条由根节点(入度为零)出发的路径中权值和最大的即为所求,dp即可解决。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stack>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 const int MAXN=1111;
  8 const int MAXM=55555;
  9 
 10 struct Edge{
 11     int v,next;
 12 }edge[MAXM];
 13 
 14 stack<int >stk;
 15 int head[MAXN],tol;
 16 int low[MAXN],pre[MAXN],sccno[MAXN],scc_cnt,TT,sccnum[MAXN];
 17 int dp[MAXN];
 18 
 19 void init()
 20 {
 21     tol=0;
 22     memset(head,-1,sizeof(head));
 23 }
 24 
 25 void add(int u,int v)
 26 {
 27     edge[tol].v=v;
 28     edge[tol].next=head[u];
 29     head[u]=tol++;
 30 }
 31 
 32 void dfs(int u)
 33 {
 34     int v;
 35     low[u]=pre[u]=++TT;
 36     stk.push(u);
 37     for(int i=head[u];i!=-1;i=edge[i].next)
 38     {
 39         v=edge[i].v;
 40         if(!pre[v]){
 41             dfs(v);
 42             low[u]=min(low[u],low[v]);
 43         }else if(!sccno[v])
 44             low[u]=min(low[u],pre[v]);
 45     }
 46     if(low[u]==pre[u]){
 47         scc_cnt++;
 48         int s=0;
 49         do{
 50             v=stk.top();
 51             stk.pop();
 52             sccno[v]=scc_cnt;
 53             s++;
 54         }while(u!=v);
 55         sccnum[scc_cnt]=s;
 56     }
 57 }
 58 
 59 void tarjan(int n)
 60 {
 61     scc_cnt=TT=0;
 62     memset(low,0,sizeof(low));
 63     memset(pre,0,sizeof(pre));
 64     memset(sccno,0,sizeof(sccno));
 65 
 66     for(int i=1;i<=n;i++)
 67         if(!pre[i])
 68             dfs(i);
 69 }
 70 
 71 int find_dfs(int u){
 72     if(dp[u])
 73         return dp[u];
 74     else if(head[u]==-1)
 75         return dp[u]=sccnum[u];
 76 
 77     int m=0;
 78     for(int i=head[u];i!=-1;i=edge[i].next)
 79     {
 80         int v=edge[i].v;
 81         m=max(m,find_dfs(v));
 82     }
 83     return dp[u]=sccnum[u]+m;
 84 }
 85 
 86 int main()
 87 {
 88     int T,n,m;
 89     int a[MAXM],b[MAXM];
 90     int in[MAXN];
 91     scanf("%d",&T);
 92     while(T--)
 93     {
 94         scanf("%d%d",&n,&m);
 95 
 96         init();
 97         for(int i=1;i<=m;i++)
 98         {
 99             scanf("%d%d",&a[i],&b[i]);
100             add(a[i],b[i]);
101         }
102         tarjan(n);
103 
104         init();
105         memset(in,0,sizeof(in));
106         for(int i=1;i<=m;i++)
107         {
108             if(sccno[a[i]]!=sccno[b[i]]){
109                 in[sccno[b[i]]]++;
110                 add(sccno[a[i]],sccno[b[i]]);
111             }
112         }
113         int s=0;
114         memset(dp,0,sizeof(dp));
115         for(int i=1;i<=scc_cnt;i++)
116             if(!in[i])
117                 s=max(s,find_dfs(i));
118         printf("%d
",s);
119     }
120     return 0;
121 }
View Code
原文地址:https://www.cnblogs.com/zstu-abc/p/3239803.html