题意:
给出一张图,求最庞大的点之间至少单向可达的集合的点的数量
思路:
想求出全部的SCC,然后在把所有的SCC当成一个点,将所有不再一个SCC里但有关联的点连起来构成DAG,dp求最大值
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<stack>
using namespace std;
const int maxn = 1005;
const int INF = 0x3f3f3f3f;
int n, m;
vector<int> g[maxn], G[maxn];
stack<int> s;
int pre[maxn], lowlink[maxn], sccno[maxn], sccnum[maxn];
int dfs_clock, scc_cnt;
void init() {
for(int i=0; i<n; i++){
g[i].clear();
}
memset(pre, 0, sizeof(pre));
memset(lowlink, 0, sizeof(lowlink));
memset(sccno, 0, sizeof(sccno));
memset(sccnum, 0, sizeof(sccnum));
dfs_clock = scc_cnt = 0;
}
void dfs(int u) {
s.push(u);
pre[u] = lowlink[u] = ++dfs_clock;
for(int i=0; i<g[u].size(); i++) {
int y = g[u][i];
if(!pre[y]) {
dfs(y);
lowlink[u] = min(lowlink[u], lowlink[y]);
}
else if(!sccno[y]) {
lowlink[u] = min(lowlink[u], pre[y]);
}
}
if(lowlink[u] == pre[u]) {
scc_cnt++;
while(1) {
int x = s.top();
s.pop();
sccno[x] = scc_cnt;
sccnum[scc_cnt]++;
if(x==u) break;
}
}
}
void find_scc() {
for(int i=0; i<n; i++) {
if(!pre[i]) {
dfs(i);
}
}
}
int d[maxn];
int dp(int x) {
if(d[x]>0) return d[x];
d[x] = sccnum[x];
for(int i=0; i<G[x].size(); i++) {
int y = G[x][i];
d[x] = max(d[x], dp(y)+sccnum[x]);
}
return d[x];
}
int main() {
int t;
scanf("%d", &t);
int a, b;
while(t--) {
scanf("%d%d", &n, &m);
init();
for(int i=0; i<m; i++) {
scanf("%d%d", &a, &b);
a--;
b--;
g[a].push_back(b);
}
find_scc();
memset(G, 0, sizeof(G));
memset(d, -1, sizeof(d));
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]) {
G[sccno[u]].push_back(sccno[v]);
}
}
}
int ans = 0;
for(int i=1; i<=scc_cnt; i++) {
ans = max(ans, dp(i));
}
printf("%d\n", ans);
}
return 0;
}
6171



被折叠的 条评论
为什么被折叠?



