首页 > 代码库 > UVAoj 11324 - The Largest Clique(tarjan + dp)

UVAoj 11324 - The Largest Clique(tarjan + dp)

题意:给定一个有向图,寻找一个点数最大集合,使得这个集合中的任意两个点
u,v, 都有u->v 或者 v->u 或者u<==>v

思路:首先将强连通分量通过tarjan算法求出来,然后进行缩点,也就是每一个缩点
所组成的图就是一个DAG图!令每一个点的权值就是这个缩点所包含节点(也就是对应的
强连通分量的节点数目),因为强连通分量的任意的两个节点都是相互可达的,那么这个
缩点要么选要么不选,问题就转换成了DAG图上的最长路径!

  1 #include<iostream>  2 #include<queue>  3 #include<stack>  4 #include<cstring>  5 #include<cstdio>  6 #include<algorithm>  7 #include<vector>  8 #define N 1005  9 using namespace std; 10  11 struct EDGE{ 12     int u, v, nt; 13     EDGE(){} 14     EDGE(int u, int v, int nt) : u(u), v(v), nt(nt){} 15 }; 16  17 int first[N]; 18 vector<EDGE>g; 19 vector<EDGE>gg; 20 int scc_cnt, dfs_clock; 21 int scc[N]; 22 int pre[N], low[N]; 23 int dp[N], cnt[N]; 24  25 int in[N]; 26 int n, m; 27 stack<int>s; 28  29 void dfs(int u){ 30     pre[u] = low[u] = ++dfs_clock; 31     s.push(u); 32     for(int i = first[u]; ~i; i = g[i].nt){ 33         int v = g[i].v; 34         if(!pre[v]){ 35             dfs(v); 36             low[u] = min(low[u], low[v]); 37         }else if(!scc[v]) 38             low[u] = min(low[u], pre[v]); 39     } 40     if(low[u] == pre[u]){ 41         ++scc_cnt; 42         while(1){ 43             ++cnt[scc_cnt]; 44             int x = s.top(); s.pop(); 45             scc[x] = scc_cnt; 46             if(x==u) break; 47         } 48     } 49 } 50  51 void addEdge(int u, int v){ 52     g.push_back(EDGE(u, v, first[u])); 53     first[u] = g.size() - 1; 54 } 55  56 void tarjans(){ 57     memset(pre, 0, sizeof(pre)); 58     memset(scc, 0, sizeof(scc)); 59     memset(cnt, 0, sizeof(cnt)); 60     memset(dp, 0, sizeof(dp)); 61     memset(in, 0, sizeof(in)); 62     scc_cnt = 0; 63     dfs_clock = 0; 64     for(int i=1; i<=n; ++i) 65         if(!pre[i]) dfs(i); 66     int len = g.size(); 67     memset(first, -1, sizeof(first)); 68     gg.clear(); 69     for(int i=0; i<len; ++i) 70         if(scc[g[i].u] != scc[g[i].v]){ 71              in[scc[g[i].v]]++; 72              gg.push_back(EDGE(scc[g[i].u], scc[g[i].v], first[scc[g[i].u]])); 73              first[scc[g[i].u]] = gg.size() - 1; 74         } 75     int maxN = 0;     76     queue<int>q; 77     for(int i=1; i<=scc_cnt; ++i) 78         if(!in[i]){ 79            dp[i] = cnt[i]; 80            q.push(i); 81            if(maxN < dp[i]) maxN = dp[i]; 82         } 83     while(!q.empty()){ 84         int u = q.front(); q.pop(); 85         for(int i=first[u]; ~i; i = gg[i].nt){ 86             int v = gg[i].v; 87             dp[v] = max(dp[v], dp[u] + cnt[v]); 88             q.push(v); 89             if(maxN < dp[v]) maxN = dp[v]; 90         } 91     } 92     printf("%d\n", maxN);  93 } 94  95 int main(){ 96     int t; 97     scanf("%d", &t); 98     while(t--){ 99         memset(first, -1, sizeof(first));100         scanf("%d%d", &n, &m);101         while(m--){102             int u, v;103             scanf("%d%d", &u, &v);104             addEdge(u, v);105         }106         tarjans();    107         g.clear();108     }109     return 0;110 } 
View Code

 

UVAoj 11324 - The Largest Clique(tarjan + dp)