题目链接:Antinomy与伊尔美格
比较明显的缩点,但是缩点之后怎么求最大值呢?
我们缩点变成DAG之后,因为求最大值,而且不能往回走,所以跑最长路即可。
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=5e5+10,M=1e6+10;
int n,m,xx[N],u,k,a[N],b[N],res,d[N];
int dfn[N],low[N],sum[N],col[N],co,cnt; bool vis[M],p[N],flag[N];
vector<int> v1[M],v2[M]; stack<int> st;
void Tarjan(int x){
dfn[x]=low[x]=++cnt; vis[x]=1; st.push(x);
for(int i=0;i<v1[x].size();i++){
int to=v1[x][i];
if(!dfn[to]){
Tarjan(to); low[x]=min(low[x],low[to]);
}else if(vis[to]) low[x]=min(low[x],dfn[to]);
}
if(low[x]==dfn[x]){
int u; co++;
do{
u=st.top(); st.pop(); vis[u]=0; sum[co]+=xx[u]; col[u]=co;
flag[co]|=p[u];
}while(u!=x);
}
}
void spfa(){
memset(d,0xcf,sizeof d); queue<int> q; q.push(u); vis[u]=1; d[u]=0;
while(q.size()){
int u=q.front(); q.pop(); vis[u]=0;
for(int i=0;i<v1[u].size();i++){
int to=v1[u][i],w=v2[u][i];
if(d[to]<d[u]+w){
d[to]=d[u]+w;
if(!vis[to]) vis[to]=1,q.push(to);
}
}
}
}
signed main(){
cin>>n>>m;
for(int i=1;i<=m;i++) scanf("%d %d",&a[i],&b[i]),v1[a[i]].push_back(b[i]);
for(int i=1;i<=n;i++) scanf("%d",&xx[i]);
cin>>u>>k;
for(int i=1,x;i<=k;i++) scanf("%d",&x),p[x]=1;
for(int i=1;i<=n;i++) if(!dfn[i]) Tarjan(i);
for(int i=1;i<=n;i++) v1[i].clear();
for(int i=1;i<=co;i++) v1[i].push_back(i+co),v2[i].push_back(sum[i]);
for(int i=1;i<=m;i++){
int u=col[a[i]],v=col[b[i]];
if(u!=v) v1[u+co].push_back(v),v2[u+co].push_back(0);
}
u=col[u];
spfa();
for(int i=1;i<=co;i++) if(flag[i]) res=max(res,d[i+co]);
cout<<res<<endl;
return 0;
}