【UVa】11324 The Largest Clique 强连通缩点+DP

来源:互联网 发布:mac ps找不到导入照片 编辑:程序博客网 时间:2024/05/11 00:06

Problem B: The Largest Clique

Given a directed graph G, consider the following transformation. First, create a new graphT(G) to have the same vertex set asG. Create a directed edge betweentwo vertices u and v inT(G) if and only if there is a pathbetween u and v in G that follows the directed edges only in the forwarddirection. This graph T(G) is often called the transitive closure of G.

We define a clique in a directed graph as a set of verticesU such thatfor any two vertices u and v in U, there is a directededge either fromu 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 graphG.It begins with a line of two integersn and m, where 0 ≤ n ≤ 1000 is the number ofvertices ofGand 0 ≤ m ≤ 50,000 is the number of directed edges of G.The vertices ofG are numbered from 1 to n.The following m lines contain two distinct integersu and vbetween 1 and n which definea directed edge fromu to v in G.

For each test case, output a single integer that is the size of the largest clique inT(G).

Sample input

15 51 22 33 14 15 2

Output for sample input

4

Zachary Friggstad


题目大意:

给一张n个结点、m条边的有向图G,求一个结点数最大的结点集,使得该结点集中任意两个结点u和v满足:要么u可以到达v,要么v可以到达u(u和v相互可达也行)。(0 <= n <= 1000,0 <= m <= 50000)结点编号1~n。


题目分析:

很明显的强连通缩点+DAG最长路。不难发现在最优方案中,同一个强连通分量中的点要么都选,要么不选。把强连通分量缩点后得到SCC图,让SCC图的结点的权值等于它代表的强连通分量的结点数,则题目转化成为求SCC图上点权最大的路径。由于SCC是一个DAG图,所以用DAG上的动态规划求解即可。


代码如下:


#include <stdio.h>#include <string.h>#include <algorithm>using namespace std ;#define clear( A , X ) memset ( A , X , sizeof A )#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )#define FF( i , a , b ) for ( int i = a ; i <= b ; ++ i )const int maxN = 1005 ;const int maxS = 20005 ;const int maxQ = 20005 ;const int maxE = 1000005 ;const int oo = 0x3f3f3f3f ;struct Edge {int v , n ;Edge () {}Edge ( int var , int next ) : v(var) , n(next) {}} ;struct DAG_DP {Edge edge[maxE] ;int adj[maxN] , cntE ;int Q[maxQ] , head , tail ;int in[maxN] ;int d[maxN] ;int dis[maxN] ;void Addedge ( int u , int v ) {edge[cntE] = Edge ( v , adj[u] ) ;adj[u] = cntE ++ ;}void Init () {cntE = 0 ;head = tail = 0 ;clear ( d , 0 ) ;clear ( in , 0 ) ;clear ( dis , 0 ) ;clear ( adj , -1 ) ;}void DEBUG ( int n ) {FF ( i , 1 , n )printf ( "d[%d] = %d\n" , i , d[i] ) ;FF ( i , 1 , n )printf ( "in[%d] = %d\n" , i , in[i] ) ;}void DP ( int n ) {int ans = 0 ;FF ( i , 1 , n ) {if ( !in[i] ) {Q[tail ++] = i ;dis[i] = d[i] ;if ( ans < dis[i] )ans = dis[i] ;}}//DEBUG ( n ) ;while ( head != tail ) {int u = Q[head ++] ;for ( int i = adj[u] ; ~i ; i = edge[i].n ) {int v = edge[i].v ;if ( dis[v] < dis[u] + d[v] ) {dis[v] = dis[u] + d[v] ;if ( ans < dis[v] )ans = dis[v] ;}if ( 0 == ( -- in[v] ) )Q[tail ++] = v ;}}printf ( "%d\n" , ans ) ;}} ;struct SCC {Edge edge[maxE] ;DAG_DP DAG ;int adj[maxN] , cntE ;int scc[maxN] , Dfn[maxN] , Low[maxN] ;int dfs_clock , scc_cnt ;int S[maxS] , ins[maxN] , top ;void Addedge ( int u , int v ) {edge[cntE] = Edge ( v , adj[u] ) ;adj[u] = cntE ++ ;}void Init () {top = 0 ;cntE = 0 ;scc_cnt = 0 ;dfs_clock = 0 ;clear ( Dfn , 0 ) ;clear ( ins , 0 ) ;clear ( adj , -1 ) ;}void Tarjan ( int u ) {Dfn[u] = Low[u] = ++ dfs_clock ;ins[u] = 1 ;S[top ++] = u ;for ( int i = adj[u] ; ~i ; i = edge[i].n ) {int v = edge[i].v ;if ( !Dfn[v] ) {Tarjan ( v ) ;Low[u] = min ( Low[u] , Low[v] ) ;}else if ( ins[v] ) {Low[u] = min ( Low[u] , Dfn[v] ) ;}}if ( Low[u] == Dfn[u] ) {++ scc_cnt ;while ( 1 ) {int v = S[-- top] ;ins[v] = 0 ;scc[v] = scc_cnt ;if ( v == u ) break ;}}}void Find_SCC ( int n ) {FF ( i , 1 , n )if ( !Dfn[i] )Tarjan ( i ) ;}void Graph_Build ( int n ) {DAG.Init () ;FF ( i , 1 , n )++ DAG.d[scc[i]] ;FF ( u , 1 , n ) {for ( int i = adj[u] ; ~i ; i = edge[i].n ) {int v = edge[i].v ;if ( scc[u] != scc[v] ) {DAG.Addedge ( scc[u] , scc[v] ) ;++ DAG.in[scc[v]] ;}}}}} ;SCC scc ;void work () {int n , m , u , v ;scc.Init () ;scanf ( "%d%d" , &n , &m ) ;REP ( i , m ) {scanf ( "%d%d" , &u , &v ) ;scc.Addedge ( u , v ) ;}scc.Find_SCC ( n ) ;if ( scc.scc_cnt == 1 ) {printf ( "%d\n" , n ) ;return ;}scc.Graph_Build ( n ) ;scc.DAG.DP ( n ) ;}int main () {int T ;scanf ( "%d" , &T ) ;while ( T -- )work () ;return 0 ;}


0 0
原创粉丝点击