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\n",s); 119 } 120 return 0; 121 }