题解:P16701 [MCO 2026] 制造连招
love__luogu · · 题解
:::info[P话] 模拟赛T2,但是感觉这题不止绿。 :::
思路
考虑 DAG 上的 DP,我们设
我们用优美的语文把上面那四条给拼接起来就是
那么转移我们来讨论一下:
如果不改色的情况:
如果
否则:
改色的情况:
如果
否则:
注意我们在
:::success[代码]
const int N = 1e4 + 10;
int n,m,t,K;
int c[N];
vector<int>g[N];
ll d[N],dp[N][65][65][2];
int indu[N],outdu[N];
void solve(){
cin>>n>>m>>K>>t;
for(int i = 1;i <= n;++i) cin>>d[i]>>c[i];
for(int i = 1;i <= m;++i){
int u,v;
cin>>u>>v;
u++,v++;
indu[v]++;
g[u].pb(v);
}
for(int i = 1; i <= n; ++i)for(int k = 0; k <= 32; ++k)for(int l = 1; l <= 32; ++l)dp[i][k][l][0] = dp[i][k][l][1] = -1;
K = min(K, 30);
for(int i = 1;i <= n;++i){
dp[i][0][1][0] = d[i];
if(c[i] != t) dp[i][1][1][1] = d[i];
}
queue<int>q;
for(int i = 1;i <= n;++i){
if(indu[i] == 0) q.push(i);
}
ll ans = 0;
bool flag = false;
while(!q.empty()){
int u = q.front();
q.pop();
for(int k = 0;k <= K;++k){
for(int p = 0;p <= 1;++p){
for(int l = 1;l <= 31;++l){
ll val = dp[u][k][l][p];
if(val == -1) continue;
ans = max(ans, val);
int cn = p ? t : c[u];
for(int v:g[u]){
if(c[v] == cn) {
if(l < 31) {
ll tw = val + d[v] * (1LL << l);
if(tw > 1e9) flag = true;
else dp[v][k][l + 1][0] = max(dp[v][k][l + 1][0], tw);
} else flag = true;
} else {
ll tw = val + d[v];
if(tw > 1e9) flag = true;
else dp[v][k][1][0] = max(dp[v][k][1][0], tw);
}
if(c[v] != t && k < K){
if(t == cn) {
if(l < 31) {
ll tw = val + d[v] * (1LL << l);
if(tw > 1e9) flag = true;
else dp[v][k + 1][l + 1][1] = max(dp[v][k + 1][l + 1][1], tw);
} else flag = true;
} else {
ll tw = val + d[v];
if(tw > 1e9) flag = true;
else dp[v][k + 1][1][1] = max(dp[v][k + 1][1][1], tw);
}
}
}
}
}
}
for(int v:g[u]){
indu[v]--;
if(indu[v] == 0) q.push(v);
}
}
if(flag || ans > 1e9) cout<<-1<<"\n";
else cout<<ans<<"\n";
}
:::