Problem B: The Largest Clique
Given a directed graph G, consider the following
transformation. First, create a new graph T(G) to have the
same vertex set as G. Create a directed edge between two
vertices u and v in T(G) if
and only if there is a path
between u and v in G that
follows the directed edges only in the forward direction. This
graph T(G) is often called the transitive
closure of G.
We define a clique in a directed graph as a set of
vertices U such that for any two
vertices u and v in U, there
is a directed edge either from u to v or
from v to u (or both). The size of a
clique is the number of vertices in the clique.
The number of cases is given on the first line of input. Each test case
describes a graph G. It begins with a line of two
integers n and m, where
0 ≤ n ≤ 1000 is the number of vertices
of G and 0 ≤ m ≤ 50,000 is the
number of directed edges of G. The vertices
of G are numbered from 1 to n. The
following m lines contain two distinct
integers u and v between 1
and n which define a directed edge
from u to v in G.
For each test case, output a single integer that is the size of the largest
clique in T(G).
Sample input
1
5 5
1 2
2 3
3 1
4 1
5 2
Output for sample input
4
Zachary Friggstad
强连通分量缩点成DAG,求点集最大的路径。
1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5 #include <stack>
6 #include <vector>
7
8 using namespace std;
9
10 const int MAX_N = 1005;
11 const int edge = 5e4 + 5;
12 int N,M;
13 int low[MAX_N],pre[MAX_N],cmp[MAX_N];
14 int first[MAX_N],Next[edge],v[edge];
15 int ind[MAX_N],oud[MAX_N];
16 int dfs_clock,scc_cnt;
17 int dep[MAX_N];
18 int num[MAX_N];
19 stack <int > S;
20 vector<int > G[MAX_N];
21
22
23 void dfs(int u) {
24 pre[u] = low[u] = ++dfs_clock;
25 S.push(u);
26 for(int e = first[u]; e != -1; e = Next[e]) {
27 if(!pre[ v[e] ]) {
28 dfs(v[e]);
29 low[u] = min(low[u],low[ v[e] ]);
30 } else if( !cmp[ v[e] ]) {
31 low[u] = min(low[u],pre[ v[e] ]);
32 }
33 }
34
35 if(pre[u] == low[u]) {
36 ++scc_cnt;
37 for(;;) {
38 int x = S.top(); S.pop();
39 cmp[x] = scc_cnt;
40 num[scc_cnt]++;
41 if(x == u) break;
42 }
43 }
44 }
45 void scc() {
46 dfs_clock = scc_cnt = 0;
47 memset(cmp,0,sizeof(cmp));
48 memset(pre,0,sizeof(pre));
49
50 for(int i = 1; i <= N; ++i) if(!pre[i]) dfs(i);
51 }
52
53 void dfs1(int u) {
54 pre[u] = 1;
55 for(int i = 0; i < G[u].size(); ++i) {
56 if(!pre[ G[u][i] ]) {
57 dfs1( G[u][i] );
58 }
59 dep[u] = max(dep[u],dep[ G[u][i] ] + num[u]);
60 }
61 }
62
63 void solve() {
64 scc();
65 for(int i = 1; i <= scc_cnt; ++i) G[i].clear();
66 for(int i = 1; i <= scc_cnt; ++i) dep[i] = num[i];
67
68 for(int i = 1; i <= N; ++i) {
69 for(int e = first[i]; e != -1; e = Next[e]) {
70 if(cmp[i] == cmp[ v[e] ]) continue;
71 G[ cmp[i] ].push_back(cmp[ v[e] ]);
72 }
73 }
74
75 memset(pre,0,sizeof(pre));
76 for(int i = 1; i <= scc_cnt; ++i) {
77 if(!pre[i]) dfs1(i);
78 }
79
80 int ans = 0;
81 for(int i = 1; i <= scc_cnt; ++i) {
82 ans = max(ans,dep[i]);
83 }
84
85 printf("%d\n",ans);
86
87 }
88
89 void add_edge(int id,int u) {
90 int e = first[u];
91 Next[id] = e;
92 first[u] = id;
93 }
94 int main()
95 {
96 //freopen("sw.in","r",stdin);
97 int t;
98 scanf("%d",&t);
99 while(t--) {
100 scanf("%d%d",&N,&M);
101 for(int i = 1; i <= N; ++i) first[i] = -1;
102 memset(num,0,sizeof(num));
103
104 for(int i = 1; i <= M; ++i) {
105 int u;
106 scanf("%d%d",&u,&v[i]);
107 add_edge(i,u);
108 }
109
110 solve();
111 }
112 //cout << "Hello world!" << endl;
113 return 0;
114 }
uva 11324,码迷,mamicode.com