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 nand 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 ofG 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).
1 5 5 1 2 2 3 3 1 4 1 5 2
4
解题:强连通子图的求解,缩点,DAG上的动态规划。先求出所有的强连通子图后,再对各个强连通子图进行缩点,所谓缩点,即为把这个强连通块作为一个点,进行新图的建立。原来图上的任意一点必然属于某个强连通块。所以根据各点所在的连通块,进行新图的建立,注意方向性,DAG上的动态规划是对于有向图而言的,所以必须保证方向的正确性。建立新图后,求DAG上的最长路径即可。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <climits> 7 #include <vector> 8 #include <queue> 9 #include <cstdlib> 10 #include <string> 11 #include <set> 12 #include <stack> 13 #define LL long long 14 #define INF 0x3f3f3f3f 15 using namespace std; 16 const int maxn = 1010; 17 int low[maxn],dfn[maxn],iindex,sccBlocks; 18 bool instack[maxn],vis[maxn]; 19 int belong[maxn],val[maxn],dp[maxn],n,m; 20 stack<int>s; 21 vector<int>g[maxn]; 22 vector<int>mp[maxn]; 23 void tarjan(int u){ 24 dfn[u] = low[u] = ++iindex; 25 instack[u] = true; 26 s.push(u); 27 for(int i = 0; i < g[u].size(); i++){ 28 int v = g[u][i]; 29 if(!dfn[v]){ 30 tarjan(v); 31 low[u] = min(low[u],low[v]); 32 }else if(instack[v] && low[u] > dfn[v]) low[u] = dfn[v]; 33 } 34 if(dfn[u] == low[u]){ 35 int v; 36 sccBlocks++; 37 do{ 38 v = s.top(); 39 s.pop(); 40 instack[v] = false; 41 belong[v] = sccBlocks; 42 }while(u != v); 43 } 44 } 45 int dag(int u){ 46 if(dp[u]) return dp[u]; 47 else if(mp[u].size() == 0) return dp[u] = val[u]; 48 int ans = 0; 49 for(int v = 0; v < mp[u].size(); v++){ 50 ans = max(ans,dag(mp[u][v])); 51 } 52 return dp[u] = ans+val[u]; 53 } 54 int main(){ 55 int t,u,v,i,j; 56 scanf("%d",&t); 57 while(t--){ 58 scanf("%d%d",&n,&m); 59 for(i = 0; i <= n; i++){ 60 g[i].clear(); 61 dfn[i] = low[i] = 0; 62 instack[i] = false; 63 val[i] = belong[i] = 0; 64 dp[i] = 0; 65 mp[i].clear(); 66 } 67 for(i = 0; i < m; i++){ 68 scanf("%d%d",&u,&v); 69 g[u].push_back(v); 70 } 71 iindex = sccBlocks = 0; 72 for(i = 1; i <= n; i++) 73 if(!dfn[i]) tarjan(i); 74 for(u = 1; u <= n; u++){ 75 val[belong[u]]++; 76 memset(vis,false,sizeof(vis)); 77 for(j = 0; j < g[u].size(); j++){ 78 v = g[u][j]; 79 if(!vis[belong[v]] && belong[v] != belong[u]){ 80 vis[belong[v]] = true; 81 mp[belong[u]].push_back(belong[v]); 82 } 83 } 84 } 85 int ans = 0; 86 for(i = 1; i <= sccBlocks; i++) 87 ans = max(ans,dag(i)); 88 printf("%d\n",ans); 89 } 90 return 0; 91 }
图论trainning-part-2 C. The Largest Clique,布布扣,bubuko.com
图论trainning-part-2 C. The Largest Clique
原文:http://www.cnblogs.com/crackpotisback/p/3864070.html