专栏文章
【0】做题心得 - 2025 NOIP #67 - T2 / 题解:P13118 [GCJ 2019 #2] Contransmutation【Tarjan】【图论】【缩点】【动态规划】
题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @min1t0p8
- 此快照首次捕获于
- 2025/12/01 19:10 3 个月前
- 此快照最后确认于
- 2025/12/01 19:10 3 个月前
如此成绩,何以 PION。你首先考虑一个无限的情况是怎么样的。你会发现在强连通分量里面有完全なるの黄金回旋エネルギー,可以无限传递。当这个 SCC 内的边数与点数相等时就显然有每个点最大为他们的和。要是边数更多一点,就显然有无限传递。缩点后这就显然是一个 DAG,直接做即可。注意判断 ,也就是没有病毒的情况。
CPP#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2e5+10;
const ll P=1e9+7;
ll d[N]; bool z[N];
int n,a[N],cnt[N],deg[N];
int id[N],low[N],ic;
int sid[N],stk[N],top,sd,sz[N];
vector<int>e[N],g[N],nd[N];
bool vis[N];
void tarjan(int p){
stk[++top]=p;
id[p]=low[p]=++ic;
for(auto v:e[p]){
if(!id[v]){
tarjan(v);
low[p]=min(low[p],low[v]);
}else if(!sid[v])
low[p]=min(low[p],id[v]);
}
if(low[p]==id[p]){
++sd;
int q=stk[top];
do{
q=stk[top], --top;
sid[q]=sd;
sz[sd]++;
d[sd]=(d[sd]+a[q])%P;
z[sd]=z[sd]|bool(a[q]);
nd[sd].push_back(q);
}while(p!=q);
}
return;
}
queue<int>q;
int main(){
freopen("virus.in","r",stdin);
freopen("virus.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
int u,v;
cin>>u>>v;
e[i].push_back(u);
e[i].push_back(v);
}
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)if(!id[i])
tarjan(i);
for(int i=1;i<=n;i++)for(auto v:e[i])
if(sid[i]==sid[v]) cnt[sid[i]]++;
else g[sid[i]].push_back(sid[v]), deg[sid[v]]++;
for(int i=1;i<=sd;i++)
if(!deg[i]) q.push(i);
while(q.size()){
int p=q.front();
q.pop();
if(cnt[p]>sz[p]&&z[p]) d[p]=-1;
for(auto v:g[p]){
z[v]=z[v]|z[p];
if(d[p]==-1||d[v]==-1||(cnt[p]==sz[p]&&z[p])) d[v]=-1;
else d[v]=(d[v]+d[p])%P;
if(!(--deg[v])) q.push(v);
}
}
for(int i=1;i<=n;i++)
cout<<d[sid[i]]<<" ";
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...