Title Link: https://cn.vjudge.net/problem/UVA-11324
For a directed graph G, find a node set with the largest number of nodes, so that any two nodes u and v in the node set meet the following requirements: either u can reach v, or v can reach u, or both can reach each other.
Analysis: it is not difficult to find that in the optimal scheme, the points in the same strongly connected component are either selected or not. The SCC graph (strongly connected component) can be obtained by shrinking the strongly connected component and making the weight of each SCC node equal to its number of nodes. Then the problem is transformed into the path to find the maximum weight on the SCC graph. Since the SCC graph is a DAG, it can be solved by dynamic programming.
The code is as follows:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <stack>
using namespace std;
const int maxn =1000+10;
int T,n,m,d[maxn];
int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt,w[maxn];///How many connected components of SCC CNT can lowlink be traced back to the earliest ancestors
///sccno[i]=j indicates that i-node belongs to j-connected component
vector<int>G[maxn],mp[maxn];
stack<int>S;
void dfs(int u)
{
pre[u] = lowlink[u] = ++dfs_clock;
S.push(u);
for(int i=0; i<G[u].size(); i++)
{
int v = G[u][i];
if(!pre[v])
{
dfs(v);
lowlink[u] = min(lowlink[u],lowlink[v]);
}
else if(!sccno[v])
{
lowlink[u] = min(lowlink[u], pre[v]);
}
}
if(lowlink[u]==pre[u])
{
int cnt=0;
scc_cnt++;
for(;;)
{
cnt++;
int x = S.top();
S.pop();
sccno[x] = scc_cnt;
if(x==u)
break;
}
w[scc_cnt]=cnt;
}
}
void find_scc(int n)
{
dfs_clock = scc_cnt =0;
memset(sccno, 0 , sizeof(sccno));
memset(pre, 0, sizeof(pre));
memset(d,0,sizeof(d));
memset(w,0,sizeof(w));///Number of nodes for each strongly connected component
for(int i=0; i<n; i++)
if(!pre[i])
dfs(i);
}
void build()
{
for(int i=0; i<=n; i++)
mp[i].clear();
for(int i=1; i<=scc_cnt; i++)
for(int u=0; u<n; u++)
{
for(int i=0; i<G[u].size(); i++)
{
int v= G[u][i];
if(sccno[u]!=sccno[v])
{
mp[sccno[u]].push_back(sccno[v]);
}
}
}
}
int dp(int i)
{
int& ans =d[i];
if(ans>0)
return ans;
ans=w[i];
for(int j=0; j<mp[i].size(); j++)
{
ans=max(ans,dp(mp[i][j])+w[i]);
}
return ans;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0; i<n; i++)
G[i].clear();
for(int i=0; i<n; i++)
{
G[i].clear();
mp[i].clear();
}
for(int i=0; i<m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
u--;v--;
G[u].push_back(v);
}
find_scc(n);
int ans1=0;
for(int i=1; i<=scc_cnt; i++)
{
ans1=max(dp(i),ans1);
}
printf("%d\n",ans1);
}
return 0;
}