P3387 【模板】缩点题解
P3387 【模板】缩点
题目描述
给定一个 n n n 个点 m m m 条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。
允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。
输入格式
第一行两个正整数 n , m n,m n,m。
第二行 n n n 个整数,其中第 i i i 个数 a i a_i ai 表示点 i i i 的点权。
第三至 m + 2 m+2 m+2 行,每行两个整数 u , v u,v u,v,表示一条 u → v u\rightarrow v u→v 的有向边。
输出格式
共一行,最大的点权之和。
输入输出样例 #1
输入 #1
2 2
1 1
1 2
2 1
输出 #1
2
说明/提示
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1 0 4 1\le n \le 10^4 1≤n≤104, 1 ≤ m ≤ 1 0 5 1\le m \le 10^5 1≤m≤105, 0 ≤ a i ≤ 1 0 3 0\le a_i\le 10^3 0≤ai≤103。
- 2024-11-1 添加了 hack 数据;
思路
直接缩点即可。
代码见下
#include<bits/stdc++.h>
using namespace std;
long long n,m,aa,bb,a[200005],dfn[200005],low[200005],st[200005],n2=0,ss=0,s2[200005],df[200005],fd[200005],fd2[200005],db=0,bd=0,de[200005],sg[200005],f[200005];
vector<long long> v[200005];
vector<long long> vr[200005];
bool bo[10004][10004];
inline void abc(long long a1){
low[a1]=dfn[a1]=++n2;
st[++st[200004]]=a1;
de[a1]=1;
//cout<<st[200004]<<" "<<st[st[200004]]<<endl;
for(int i=0;i<v[a1].size();i++){
long long tt=v[a1][i];
if(de[tt]==1){
low[a1]=min(low[a1],dfn[tt]);
}
else if(de[tt]==0){
abc(tt);
low[a1]=min(low[a1],low[tt]);
}
}
if(low[a1]==dfn[a1]){
ss++;
s2[a1]=ss;
df[ss]=1;
sg[ss]=a[a1];
while(st[st[200004]]!=a1){
//cout<<st[200004]<<" "<<st[st[200004]]<<endl;
s2[st[st[200004]]]=ss;
de[st[st[200004]]]=-1;
sg[ss]+=a[st[st[200004]]];
st[200004]--;
df[ss]++;
}
//cout<<st[200004]<<" "<<st[st[200004]]<<" "<<a1<<endl;
de[st[st[200004]]]=-1;
st[200004]--;
}
//cout<<a1<<" "<<v[a1].size()<<" "<<st[200004]<<endl;
return ;
}
void abc2(long long a1){
for(int i=0;i<vr[a1].size();i++){
long long tt=vr[a1][i];
if(f[tt]<=f[a1]+sg[tt]-1){
f[tt]=f[a1]+sg[tt];
abc2(tt);
}
}
return ;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=m;i++){
cin>>aa>>bb;
v[aa].push_back(bb);
}
for(int i=1;i<=n;i++){
if(dfn[i]==0){
//cout<<"ddddddddddddddddddddddddddd"<<i<<endl;
abc(i);
}
}
for(int i=1;i<=n;i++){
for(int j=0;j<v[i].size();j++){
if(s2[i]!=s2[v[i][j]]){
if(bo[s2[i]][s2[v[i][j]]]==0){
bo[s2[i]][s2[v[i][j]]]=1;
vr[s2[i]].push_back(s2[v[i][j]]);
//cout<<i<<endl;
//cout<<st[200004]<<endl;
}
fd[s2[v[i][j]]]++;
fd2[s2[i]]++;
}
}
}
for(int i=1;i<=ss;i++){
if(fd[i]==0){
f[i]=sg[i];
abc2(i);
}
}
for(int i=1;i<=ss;i++){
bd=max(bd,f[i]);
}
// if(ss==1){
// cout<<1<<endl;
// return 0;
// }
cout<<bd<<endl;
return 0;
}

浙公网安备 33010602011771号