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

 

posted @ 2014-10-11 20:07  hjzqyx  阅读(206)  评论(0编辑  收藏  举报