Given a directed graph G, con- sider the following transformation. First, create a new graph T(G) to have the same vertex set as G. Cre- ate 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 tran- sitive 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. Input 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. Output 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 Sample Output 4The
题解:让你求至少单向可以连通的最多的节点数;
我们可以用个SCC缩点以后,然后进行记忆化搜索+DP,从没一个“点”开始,求最大值即可;
dp[x]=max(dp[x],sz[x]+DP(G[x][i]); DP为搜索函数,搜索点x的最多节点数;sz[x]为点“x”代表的点集的个数;
参考代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1010; 4 int t,n,m,u,v,times,blocks; 5 int dfn[maxn],lowv[maxn],belong[maxn],ins[maxn],sz[maxn]; 6 int dp[maxn]; 7 struct Node{ 8 int u,v; 9 Node(int _u,int _v): u(_u),v(_v) { } 10 }; 11 12 vector<Node> edges; 13 vector<int> G[maxn],GG[maxn]; 14 stack<int> st; 15 16 void Addedge(int u,int v) 17 { 18 G[u].push_back(edges.size()); 19 edges.push_back(Node(u,v)); 20 } 21 22 void Init() 23 { 24 times=blocks=0; 25 memset(dp,-1,sizeof dp); 26 memset(dfn,0,sizeof dfn); 27 memset(lowv,0,sizeof lowv); 28 memset(sz,0,sizeof sz); 29 memset(ins,0,sizeof ins); 30 memset(belong,0,sizeof belong); 31 while(!st.empty()) st.pop(); 32 edges.clear(); 33 for(int i=0;i<=n;i++) G[i].clear(); 34 } 35 36 void Tarjan(int u) 37 { 38 dfn[u]=lowv[u]=++times; 39 st.push(u); 40 ins[u]=1; 41 for(int i=0;i<G[u].size();i++) 42 { 43 int v=edges[G[u][i]].v; 44 if(!dfn[v]) Tarjan(v),lowv[u]=min(lowv[u],lowv[v]); 45 else if(ins[v]) lowv[u]=min(lowv[u],dfn[v]); 46 } 47 if(dfn[u]==lowv[u]) 48 { 49 ++blocks; 50 int v; 51 do 52 { 53 v=st.top(); st.pop(); 54 ins[v]=0; 55 belong[v]=blocks; 56 sz[blocks]++; 57 } while(u!=v); 58 } 59 } 60 61 int DP(int x) 62 { 63 if(dp[x]>0) return dp[x]; 64 dp[x]=sz[x]; 65 for(int i=0;i<GG[x].size();i++) dp[x]=max(dp[x],DP(GG[x][i])+sz[x]); 66 return dp[x]; 67 } 68 69 70 int main() 71 { 72 ios::sync_with_stdio(false); 73 cin>>t; 74 while(t--) 75 { 76 cin>>n>>m; 77 Init(); 78 for(int i=1;i<=m;i++) 79 { 80 cin>>u>>v; 81 Addedge(u,v); 82 } 83 for(int i=1;i<=n;i++) if(!dfn[i]) Tarjan(i); 84 for(int i=0;i<=n;i++) GG[i].clear(); 85 for(int i=1;i<=n;i++) 86 { 87 for(int j=0;j<G[i].size();j++) 88 { 89 if(belong[i]!=belong[edges[G[i][j]].v]) 90 GG[belong[i]].push_back(belong[edges[G[i][j]].v]); 91 } 92 } 93 int ans=0; 94 for(int i=1;i<=blocks;i++) ans=max(ans,DP(i)); 95 cout<<ans<<endl; 96 } 97 return 0; 98 }