EC-Final 2022 (UCup Stage 11) A.Coloring
_jimmywang_ · · 题解
晃了一圈没找到题解,官方题解又简略的很,因此记之。
首先对所有
先不考虑这个
由于上面的连边方式,每次
其中
显然越多的变换次数会给子树带来更多可能性,当也会增加
需要对
如果
记 请自己手摸尝试证明或感性理解。
而且反过来,任意一组满足上述条件的 还是请自己手摸尝试感性理解。
因此在环上,我们可枚举
做完了,有一些细节,然后是代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define f(i,a,b) for(ll i=a;i<=b;i++)
inline ll rd(){
ll x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c))x=x*10+c-'0',c=getchar();
return x*f;
}
#define d rd()
ll n,m,s;
ll w[5010],p[5010];
vector<ll>e[5010],ee[5010];
ll in[5010];
bool vis[5010];
queue<ll>q;
ll dis[5010];
ll dp[5010][5010];
void dfs(ll u){
f(i,0,n){
ll x=(i&1);if(u==s)x^=1;
dp[u][i]=x*w[u]-i*p[u];
}for(int i=0;i<e[u].size();i++){
ll v=e[u][i];if(!vis[v])continue;
dfs(v);ll mx=dp[v][0];
f(j,0,n)dp[u][j]+=(u==s?max(mx,dp[v][j+1]):mx),mx=max(mx,dp[v][j+1]);
}dp[u][n+1]=-1e18;
}
ll lp[5010],cl;
void dfl(ll u){
if(u==s&&cl)return;
lp[++cl]=u;
for(int i=0;i<e[u].size();i++){
ll v=e[u][i];if(vis[v])continue;
dfl(v);
}
}
ll sum[5010][5010];
ll f[5010][3],res=-1e18;
#define Max(a,b) (a>b?a:b)
int main(){
n=d,s=d;f(i,1,n)w[i]=d;f(i,1,n)p[i]=d;
f(i,1,n){
ll x=d;e[x].push_back(i);
ee[i].push_back(x);in[x]++;
}f(i,1,n)if(!in[i])q.push(i);
while(!q.empty()){
ll u=q.front();q.pop();
vis[u]=1;for(int i=0;i<ee[u].size();i++){
ll v=ee[u][i];if(in[v]&&!(--in[v]))q.push(v);
}
}if(vis[s]){
dfs(s);cout<<max(dp[s][0],dp[s][1]);return 0;
}dfl(s);f(i,1,cl)dfs(lp[i]);
if(cl==2){
cout<<max(dp[s][0]+dp[lp[2]][1],max(dp[s][1]+dp[lp[2]][0],dp[s][0]+dp[lp[2]][0]));
return 0;
}
f(k,1,n+1){
f[1][0]=dp[s][k-1],f[1][1]=f[1][2]=-1e18;
f(i,2,cl){
f[i][0]=f[i-1][0]+dp[lp[i]][k];
f[i][1]=max(f[i-1][0],f[i-1][1])+dp[lp[i]][k-1];
if(k>=2)f[i][2]=max(f[i-1][0],max(f[i-1][1],f[i-1][2]))+dp[lp[i]][k-2];
if(f[i][0]<-1e18)f[i][0]=-1e18;
if(f[i][1]<-1e18)f[i][1]=-1e18;
if(f[i][2]<-1e18)f[i][2]=-1e18;
}res=max(res,max(f[cl][1],f[cl][0]));
if(k>=2)res=max(res,f[cl][2]);
}cout<<res;
return 0;
}