Tarjan 杂题
P5676 [GZOI2017] 小z玩游戏
将有趣程度作为点来建图 相当于是看哪些游戏的
这样是
考虑换一种建边方式
若当前兴奋值为
可以视为兴奋值先从
那我们就可以对每个数向它的倍数建边,再对于每个游戏从
跑一遍
#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define inl inline
#define eb emplace_back
#define endl '\n'
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
#define fi first
#define se second
#define mkp make_pair
#define print(x) cerr<<#x<<'='<<x<<endl
#define getchar() cin.get()
const int inf = 0x3f3f3f3f;
const int N = 1e5 + 5;
const int maxn = 1e5;
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f;
}
int n , ee[N] , w[N] , ans;
int low[N] , dfn[N] , timer , in[N] , id[N] , tot , sta[N] , top;
vector<int> e[N];
inl void add ( int u , int v ) { e[u].eb(v); }
void tarjan ( int u )
{
dfn[u] = low[u] = ++ timer;
sta[++top] = u , in[u] = 1;
for ( auto v : e[u] )
{
if ( !dfn[v] ) tarjan(v) , low[u] = min ( low[u] , low[v] );
else if ( in[v] ) low[u] = min ( low[u] , dfn[v] );
}
if ( low[u] == dfn[u] )
{
++ tot;
while ( top )
{
int x = sta[top--];
id[x] = tot , in[x] = 0;
if ( x == u ) break;
}
}
}
void init()
{
for ( int i = 1 ; i <= maxn ; i ++ ) e[i].clear();
ans = timer = top = tot = 0;
memset ( dfn , 0 , sizeof dfn );
memset ( id , 0 , sizeof id );
memset ( in , 0 , sizeof in );
}
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
int T = read();
while ( T -- )
{
init();
for ( int i = 1 ; i <= maxn ; i ++ )
for ( int j = 2 ; j * i <= maxn ; j ++ )
add ( i , j * i );
n = read();
for ( int i = 1 ; i <= n ; i ++ ) w[i] = read();
for ( int i = 1 ; i <= n ; i ++ ) ee[i] = read();
for ( int i = 1 ; i <= n ; i ++ ) add ( w[i] , ee[i] );
for ( int i = 1 ; i <= maxn ; i ++ ) if ( !dfn[i] ) tarjan(i);
for ( int i = 1 ; i <= n ; i ++ ) if ( id[w[i]] == id[ee[i]] ) ++ ans;
cout << ans << endl;
}
return 0;
}
P1653 [USACO04DEC] Cow Ski Area G
每一个合法节点和它相邻的合法四个节点连边 跑一边
#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define inl inline
#define eb emplace_back
#define endl '\n'
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
#define fi first
#define se second
#define mkp make_pair
#define print(x) cerr<<#x<<'='<<x<<endl
#define getchar() cin.get()
const int inf = 0x3f3f3f3f;
const int N = 500 * 500 + 5;
const int M = 500 + 5;
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f;
}
int n , m , sumrd , sumcd , a[M][M] , rd[N] , cd[N];
int low[N] , dfn[N] , timer , in[N] , id[N] , tot , sta[N] , top;
vector<int> e[N];
inl void adde ( int u , int v ) { e[u].eb(v); }
inl int check ( int u , int v ) { return 1 <= u && u <= n && 1 <= v && v <= m; }
inl int pos ( int u , int v ) { return ( u - 1 ) * m + v; }
inl void add ( int u , int v , int p , int q )
{
if ( !check ( p , q ) ) return;
if ( a[u][v] >= a[p][q] ) adde ( pos ( u , v ) , pos ( p , q ) );
}
void tarjan ( int u )
{
dfn[u] = low[u] = ++ timer;
sta[++top] = u , in[u] = 1;
for ( auto v : e[u] )
{
if ( !dfn[v] ) tarjan(v) , low[u] = min ( low[u] , low[v] );
else if ( in[v] ) low[u] = min ( low[u] , dfn[v] );
}
if ( low[u] == dfn[u] )
{
++ tot;
while ( top )
{
int x = sta[top--];
id[x] = tot , in[x] = 0;
if ( x == u ) break;
}
}
}
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
m = read() , n = read();
for ( int i = 1 ; i <= n ; i ++ ) for ( int j = 1 ; j <= m ; j ++ ) a[i][j] = read();
for ( int i = 1 ; i <= n ; i ++ ) for ( int j = 1 ; j <= m ; j ++ ) add ( i , j , i , j + 1 ) , add ( i , j , i , j - 1 ) , add ( i , j , i + 1 , j ) , add ( i , j , i - 1 , j );
for ( int i = 1 ; i <= n * m ; i ++ ) if ( !dfn[i] ) tarjan(i);
if ( tot == 1 ) return cout << 0 << endl , 0;
for ( int u = 1 ; u <= n * m ; u ++ ) for ( auto v : e[u] ) if ( id[u] != id[v] ) ++ cd[id[u]] , ++ rd[id[v]];
for ( int i = 1 ; i <= tot ; i ++ )
sumrd += ( rd[i] == 0 ) , sumcd += ( cd[i] == 0 );
cout << max ( sumrd , sumcd ) << endl;
return 0;
}
P2321 [HNOI2006] 潘多拉的宝盒
相当于是我们将合法的 由
对于加边 我们可以同时让
否则 如果搜完都没有找到这样的节点 那么我们可以将
#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define inl inline
#define eb emplace_back
#define endl '\n'
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
#define fi first
#define se second
#define mkp make_pair
#define print(x) cerr<<#x<<'='<<x<<endl
#define getchar() cin.get()
const int inf = 0x3f3f3f3f;
const int N = 500 + 5;
const int M = 500 + 5;
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f;
}
int s , n , m , vis[N][N] , f[N] , flag , maxx;
struct node { int son[N][2] , mark[N]; } a[N];
int low[N] , dfn[N] , timer;
int scc[N] , id[N] , tot;
int in[N] , sta[N] , top;
vector<int> e[N] , ee[N];
inl void add ( int u , int v ) { e[u].eb(v); }
inl void adde ( int u , int v ) { ee[u].eb(v); }
void tarjan ( int u )
{
dfn[u] = low[u] = ++ timer;
sta[++top] = u , in[u] = 1;
for ( auto v : e[u] )
{
if ( !dfn[v] ) tarjan(v) , low[u] = min ( low[u] , low[v] );
else if ( in[v] ) low[u] = min ( low[u] , dfn[v] );
}
if ( low[u] == dfn[u] )
{
++ tot;
while ( top )
{
int x = sta[top--];
id[x] = tot , in[x] = 0 , ++ scc[tot];
if ( x == u ) break;
}
}
}
void check ( int u , int v , int x , int y )
{
if ( vis[x][y] || !flag ) return;
vis[x][y] = 1;
if ( a[u].mark[x] && !a[v].mark[y] ) return flag = 0 , void();
check ( u , v , a[u].son[x][0] , a[v].son[y][0] );
check ( u , v , a[u].son[x][1] , a[v].son[y][1] );
}
void dp()
{
for ( int u = tot ; u ; u -- )
for ( auto v : ee[u] )
f[v] = max ( f[v] , f[u] + scc[v] );
}
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
s = read();
for ( int i = 1 ; i <= s ; i ++ )
{
n = read() , m = read();
for ( int j = 1 ; j <= m ; j ++ ) a[i].mark[read()+1] = 1;
for ( int j = 1 ; j <= n ; j ++ ) a[i].son[j][0] = read() + 1 , a[i].son[j][1] = read() + 1;
}
for ( int i = 1 ; i <= s ; i ++ )
for ( int j = 1 ; j <= s ; j ++ )
if ( i != j )
{
flag = 1 , memset ( vis , 0 , sizeof vis );
check ( i , j , 1 , 1 );
if ( flag ) add ( i , j );
}
for ( int i = 1 ; i <= s ; i ++ ) if ( !dfn[i] ) tarjan(i);
for ( int u = 1 ; u <= s ; u ++ ) for ( auto v : e[u] ) if ( id[u] != id[v] ) adde ( id[u] , id[v] );
for ( int i = 1 ; i <= tot ; i ++ ) f[i] = scc[i];
dp();
for ( int i = 1 ; i <= tot ; i ++ ) maxx = max ( maxx , f[i] );
cout << maxx << endl;
return 0;
}
P2941 [USACO09FEB] Surround the Islands
这题目是真的绕 相当于是统计一个点到其他所有点的边权
相当于是将整张图缩点 然后输入时将两个岛屿之间的边权取
#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define inl inline
#define eb emplace_back
#define endl '\n'
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
#define fi first
#define se second
#define mkp make_pair
#define print(x) cerr<<#x<<'='<<x<<endl
#define getchar() cin.get()
const int inf = 0x3f3f3f3f;
const int N = 5e3 + 5;
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f;
}
int n , a[N][N] , ans = inf;
int low[N] , dfn[N] , timer;
int id[N] , tot;
int sta[N] , top , in[N];
vector<int> e[N];
inl void add ( int u , int v ) { e[u].eb(v); }
void tarjan ( int u )
{
dfn[u] = low[u] = ++ timer;
sta[++top] = u , in[u] = 1;
for ( auto v : e[u] )
{
if ( !dfn[v] ) tarjan(v) , low[u] = min ( low[u] , low[v] );
else if ( in[v] ) low[u] = min ( low[u] , dfn[v] );
}
if ( low[u] == dfn[u] )
{
++ tot;
while ( top )
{
int x = sta[top--];
id[x] = tot , in[x] = 0;
if ( x == u ) break;
}
}
}
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
n = read();
memset ( a , inf , sizeof a );
for ( int i = 1 , u , v ; i <= n ; i ++ ) u = read() , v = read() , add ( u , v ) , add ( v , u );
for ( int i = 1 ; i <= n ; i ++ ) if ( !dfn[i] ) tarjan(i);
for ( int i = 1 ; i <= n ; i ++ ) for ( int j = 1 , val ; j <= n ; j ++ ) a[id[i]][id[j]] = min ( a[id[i]][id[j]] , read() );
// for ( int i = 1 ; i <= n ; i ++ ) for ( int j = 1 ; j <= n ; j ++ ) cout << a[i][j] << ' ';
for ( int i = 1 ; i <= tot ; i ++ )
{
int sum = 0;
for ( int j = 1 ; j <= tot ; j ++ ) sum += a[i][j];
ans = min ( ans , sum );
}
cout << ( ans << 1 ) << endl;
return 0;
}
P3225 [HNOI2012] 矿场搭建
三倍经验:
BUSINESS - Mining your own business
一道好题 我们可以先将所有的点双求出来 我们可以为它们建一棵树(不用实际去建)
考虑统计答案 如果这个连通块内没有割点 那么必须建立至少两个 保证一个被断之后另一个还可以发挥作用 方案个数就是
如果这个连通块内有一个割点 说明是叶子节点 必须建立一个出口(在非割点上)因为这样如果断掉割点 其他点也可以跑 上面的点可以从它们父亲所能到达的其他叶子节点的出口逃跑 那么我们计入答案为
如果这个连通块内有两个以上割点 说明一个点都不需要建 因为如果一个割点断了 另一个割点一定没断 可以合并到另一个双连通分量中逃跑
#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define inl inline
#define eb emplace_back
#define endl '\n'
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
#define fi first
#define se second
#define mkp make_pair
#define print(x) cerr<<#x<<'='<<x<<endl
#define getchar() cin.get()
#define int unsigned long long
const int N = 5e4 + 5;
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f;
}
int n , m , cases , cnt , sum , cut[N];
int low[N] , dfn[N] , timer;
int id[N] , tot;
int sta[N] , top;
vector<int> e[N] , dcc[N];
inl void add ( int u , int v ) { e[u].eb(v); }
void tarjan ( int u , int rt )
{
int child = 0;
dfn[u] = low[u] = ++ timer;
sta[++top] = u;
for ( auto v : e[u] )
if ( !dfn[v] )
{
tarjan(v,rt) , low[u] = min ( low[u] , low[v] );
if ( dfn[u] <= low[v] )
{
++ child , ++ tot;
if ( u != rt || child > 1 ) cut[u] = 1;
while ( top )
{
int x = sta[top--];
dcc[tot].eb(x);
if ( x == v ) break;
}
dcc[tot].eb(u);
}
}
else low[u] = min ( low[u] , dfn[v] );
}
void init()
{
for ( int i = 1 ; i <= n ; i ++ ) e[i].clear();
for ( int i = 1 ; i <= tot ; i ++ ) dcc[i].clear();
memset ( cut , 0 , sizeof cut );
timer = top = tot = cnt = 0; sum = 1;
memset ( dfn , 0 , sizeof dfn );
}
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
while ( 1 )
{
init();
m = read(); if ( !m ) break;
for ( int i = 1 , u , v ; i <= m ; i ++ ) u = read() , v = read() , add ( u , v ) , add ( v , u ) , n = max ( n , max ( u , v ) );
for ( int i = 1 ; i <= n ; i ++ ) if ( !dfn[i] ) tarjan(i,i);
for ( int i = 1 ; i <= tot ; i ++ )
{
int sz = dcc[i].size() , cntcut = 0;
for ( auto v : dcc[i] ) cntcut += cut[v];
if ( cntcut == 1 ) ++ cnt , sum *= sz - 1;
if ( cntcut == 0 ) cnt += 2 , sum *= sz * ( sz - 1 ) / 2;
}
cout << "Case " << ++ cases << ": " << cnt << ' ' << sum << endl;
}
return 0;
}
P3119 [USACO15JAN] Grass Cownoisseur G
显然是首先来缩点
那么对于新图上的所有边 我们直接建立分层图 在加边
#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define inl inline
#define eb emplace_back
#define endl '\n'
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
#define fi first
#define se second
#define mkp make_pair
#define print(x) cerr<<#x<<'='<<x<<endl
#define getchar() cin.get()
const int N = 2e5 + 5;
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f;
}
int n , m , u[N] , v[N];
int low[N] , dfn[N] , timer;
int id[N] , tot , scc[N];
int in[N] , sta[N] , top;
vector<int> e[N] , ee[N];
inl void add ( int u , int v ) { e[u].eb(v); }
inl void adde ( int u , int v ) { ee[u].eb(v); }
void tarjan ( int u )
{
dfn[u] = low[u] = ++timer;
sta[++top] = u , in[u] = 1;
for ( auto v : e[u] )
{
if ( !dfn[v] ) tarjan(v) , low[u] = min ( low[u] , low[v] );
else if ( in[v] ) low[u] = min ( low[u] , dfn[v] );
}
if ( dfn[u] == low[u] )
{
++ tot;
while ( top )
{
int x = sta[top--];
in[x] = 0 , id[x] = tot , ++ scc[tot];
if ( x == u ) break;
}
}
}
queue<int> q;
int dis[N];
void spfa ()
{
memset ( in , 0 , sizeof in );
q.push(id[1]); in[id[1]] = 1;
while ( !q.empty() )
{
int u = q.front(); q.pop(); in[u] = 0;
for ( auto v : ee[u] )
if ( dis[v] < dis[u] + scc[v] )
{
dis[v] = dis[u] + scc[v];
if ( !in[v] ) q.push(v) , in[v] = 1;
}
}
}
signed main ()
{
// freopen ( "a.in" , "r" , stdin );
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
n = read() , m = read();
for ( int i = 1 ; i <= m ; i ++ ) u[i] = read() , v[i] = read() , add ( u[i] , v[i] );
for ( int i = 1 ; i <= n ; i ++ ) if ( !dfn[i] ) tarjan(i);
for ( int i = 1 ; i <= m ; i ++ ) if ( id[u[i]] != id[v[i]] ) adde ( id[u[i]] , id[v[i]] ) , adde ( id[u[i]] + tot , id[v[i]] + tot ) , adde ( id[v[i]] , id[u[i]] + tot );
for ( int i = 1 ; i <= tot ; i ++ ) scc[i+tot] = scc[i];
spfa();
cout << max ( dis[id[1]] , dis[tot+id[1]]) << endl;
return 0;
}
P9431 [NAPC-#1] Stage3 - Jump Refreshers
一定注意 在图中
#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define inl inline
#define eb emplace_back
#define endl '\n'
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
#define fi first
#define se second
#define mkp make_pair
#define pii pair<int,int>
#define print(x) cerr<<#x<<'='<<x<<endl
#define getchar() cin.get()
const int N = 3e4 + 5;
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f;
}
int n , d , s , x[N] , y[N] , f[N];
vector<int> e[N] , ee[N];
inl void add ( int u , int v ) { e[u].eb(v); }
inl void adde ( int u , int v ) { ee[u].eb(v); }
int dfn[N] , low[N] , timer;
int sta[N] , in[N] , top;
int id[N] , scc[N] , tot;
void tarjan ( int u )
{
dfn[u] = low[u] = ++timer;
in[sta[++top] = u] = 1;
for ( auto v : e[u] )
{
if ( !dfn[v] ) tarjan(v) , low[u] = min ( low[u] , low[v] );
else if ( in[v] ) low[u] = min ( low[u] , dfn[v] );
}
if ( dfn[u] == low[u] )
{
++ tot;
while ( top )
{
int x = sta[top--];
++ scc[tot] , in[x] = 0 , id[x] = tot;
if ( x == u ) break;
}
}
}
int check ( int i , int j )
{
return y[i] + d - y[j] >= abs ( x[i] - x[j] );
}
void init()
{
for ( int i = 1 ; i <= n ; i ++ ) e[i].clear() , ee[i].clear();
memset ( dfn , 0 , sizeof dfn );
memset ( id , 0 , sizeof id );
memset ( scc , 0 , sizeof scc );
memset ( f , 0 , sizeof f );
timer = tot = top = 0;
}
int dfs ( int u )
{
if ( f[u] ) return f[u];
f[u] = scc[u];
for ( auto v : ee[u] )
f[u] = max ( f[u] , scc[u] + dfs(v) );
return f[u];
}
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
int T = read() , temp = read();
while ( T -- )
{
init();
n = read() , d = read() , s = read();
for ( int i = 1 ; i <= n ; i ++ ) x[i] = read() , y[i] = read();
for ( int i = 1 ; i <= n ; i ++ )
for ( int j = 1 ; j <= n ; j ++ )
if ( check ( i , j ) ) add ( i , j );
for ( int i = 1 ; i <= n ; i ++ ) if ( !dfn[i] ) tarjan(i);
for ( int u = 1 ; u <= n ; u ++ )
for ( auto v : e[u] )
if ( id[u] != id[v] ) adde ( id[u] , id[v] );
cout << dfs(id[s]) << endl;
}
return 0;
}
[P2515 HAOI2010] 软件安装
对于一个环内的东西 要么都安装 要么都不安装
那么缩点之后进行树上背包即可()
#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define inl inline
#define eb emplace_back
#define endl '\n'
#define pii pair<int,int>
#define mkp make_pair
#define print(x) cerr<<#x<<'='<<x<<endl
#define getchar() cin.get()
const int N = 1e3 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 998244353;
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f;
}
int n , m , v[N] , w[N] , rd[N] , f[N][N];
vector<int> e[N] , ee[N];
inl void add ( int u , int v ) { e[u].eb(v); }
inl void adde ( int u , int v ) { ee[u].eb(v); }
int dfn[N] , low[N] , timer;
int sta[N] , in[N] , top;
int id[N] , sccv[N] , sccw[N] , tot;
void tarjan ( int u )
{
dfn[u] = low[u] = ++ timer;
sta[++top] = u , in[u] = 1;
for ( auto v : e[u] )
if ( !dfn[v] ) tarjan(v) , low[u] = min ( low[u] , low[v] );
else if ( in[v] ) low[u] = min ( low[u] , dfn[v] );
if ( dfn[u] == low[u] )
{
++ tot;
while ( top )
{
int x = sta[top--];
id[x] = tot , sccv[tot] += v[x] , sccw[tot] += w[x] , in[x] = 0;
if ( x == u ) break;
}
}
}
void dfs ( int u , int ff )
{
for ( int i = sccv[u] ; i <= m ; i ++ ) f[u][i] = sccw[u];
for ( auto v : ee[u] )
{
dfs ( v , u );
for ( int j = m ; j >= sccv[u] ; j -- )
for ( int k = sccv[v] ; k <= j - sccv[u] ; k ++ )
f[u][j] = max ( f[u][j] , f[u][j-k] + f[v][k] );
}
}
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
n = read() , m = read();
for ( int i = 1 ; i <= n ; i ++ ) v[i] = read();
for ( int i = 1 ; i <= n ; i ++ ) w[i] = read();
for ( int i = 1 , ff ; i <= n ; i ++ ) ff = read() , add ( ff , i );
for ( int i = 1 ; i <= n ; i ++ ) if ( !dfn[i] ) tarjan(i);
for ( int u = 1 ; u <= n ; u ++ )
for ( auto v : e[u] ) if ( id[u] != id[v] ) adde ( id[u] , id[v] ) , ++ rd[id[v]];
for ( int i = 1 ; i <= tot ; i ++ ) if ( !rd[i] ) adde ( 0 , i );
dfs ( 0 , 0 );
cout << f[0][m] << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效