UVA11324 The Lagest Lique(SCC缩点+DP)

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 }
View Code
原文地址:https://www.cnblogs.com/csushl/p/9632935.html