uva 11324

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

时间: 2024-09-29 00:26:16

uva 11324的相关文章

UVA 11324 The Largest Clique (强连通分量缩点,图DP)

题目: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=show_problem&problem=2299 题意: 给你一个有向图,求一个点集合的最大大小,使得此点集合中对于任意点对(u,v),有从u到v或者从v到u的边 方法: 先找强连通分量缩点,每个强连通分量显然满足条件,然后在缩点后的图中找到一条权值最大的路径,权值为此路径的点权之和,点权为这个

UVA - 11324 The Largest Clique 强连通缩点+记忆化dp

题目要求一个最大的弱联通图. 首先对于原图进行强连通缩点,得到新图,这个新图呈链状,类似树结构. 对新图进行记忆化dp,求一条权值最长的链,每个点的权值就是当前强连通分量点的个数. /* Tarjan算法求有向图的强连通分量set记录了强连通分量 Col记录了强连通分量的个数. */ #include <iostream> #include<cstring> #include<cstdio> #include<string> #include<algo

uva 11324 The Largest Clique(强连通分量缩点+DAG动态规划)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=show_problem&problem=2299 题意:输入n和m,有n个点和m条有向边,求出一个节点集合包括的节点个数最多,而且该节点内的不论什么两点a,b,要么a能到达b,要么b能到达a,要么a和b互相到达. 思路:强连通分量缩点形成有向无环图DAG,把缩点后的每一个点的权值置为该强连通分量的节点个

UVA 11324 - The Largest Clique(强连通分量+缩点)

UVA 11324 - The Largest Clique 题目链接 题意:给定一个有向图,要求找一个集合,使得集合内任意两点(u, v)要么u能到v,要么v能到u,问最大能选几个点 思路:强连通分量,构造出scc之后,缩点,每个点的权值是集合点个数,然后做一遍dag找出最大权值路径即可 代码: #include <cstdio> #include <cstring> #include <vector> #include <stack> #include

The Largest Clique UVA - 11324 (有向图最大团)

The Largest Clique UVA - 11324 题意:有向图最大团.求任意两点可达(不是互达)的最多点数. 先求出SCC,然后缩点,新图就变成了一个DAG,每个点的权值为内点的个数,用DP求解最大值. 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxv=1010; 4 5 int n,m; 6 7 vector<int> G[maxv]; 8 int pre[maxv],lowlink[

The Largest Clique UVA - 11324

题文:https://vjudge.net/problem/UVA-11324 题解: 这个题目首先可以发现,只要是一个强连通分量,要么都选,要么都不选,将点权看成强连通分量的点数,所以这个题目就转化成了DAG上的最大路. 稍微dp一下就好了. 代码: #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #in

UVA - 11324 The Largest Clique (DAG + 强连通分量)

题目大意:给出一张有向图G,求一个结点数最大的结点集,使得该点集中任意两个结点u和v满足: 要么u可到达v,要么v可以到达u(u和v互相可达也可以) 解题思路:u和v相互可达的时候,就是两个结点在同一个强连通分量内的时候 首先要保证集合里面的点可达:强连通分量就满足集合内的点都相互可达.所以第一件事就是找出所有的强连通分量,并统计出每个强连通分量内的结点数 然后找出每个强连通分量之间的关系,也就是找出两个强连通分量之间的桥,连接可连接的强连通分量 最后将每个强连通分量收缩,得到SCC图.此时的S

UVA 11324.The Largest Clique tarjan缩点+拓扑dp

题目链接:https://vjudge.net/problem/UVA-11324 题意:求一个有向图中结点数最大的结点集,使得该结点集中任意两个结点u和v满足:要目u可以到达v,要么v可以到达u(相互可达也可以). 思路:同一个强联通分量中满足结点集中任意两个结点u和v满足:要目u可以到达v,要么v可以到达u(相互可达也可以).把强联通分量收缩点后得到scc图,让每个scc结点的权值等于他的结点数,则求scc图上权最大的路径.拓扑dp,也可以直接bfs,但是要建立一个新的起点,连接所有入度为0

UVA 11324 The Largest Clique

给出一个有向图,求一个最大的结点集合,任意两个点u,v.u可到达v或v可到达u. 一个强连通分量肯定一起选的.所以先找出所有scc,然后缩点以后跑DAG上的dp. 注意0,0这组数据 #include<bits/stdc++.h> using namespace std; const int maxn = 1005,maxm = 5e5+1; int head[maxn],to[maxm],nxt[maxm]; void addEdge(int u,int v,int i) { to[i] =