标签:缩点 stream head read target pen for 模板 http
P3387【模板】缩点
注释放代码里啦
时间复杂度O(n+m)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define maxn 100010
#define maxm 1000010
using namespace std;
template<typename T>
inline void read(T &x){
x=0;bool flag=0;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c==‘-‘) flag=1;
for(;isdigit(c);c=getchar()) x=x*10+(c^48);
if(flag) x=-x;
}
int n,m,w[maxn],x[maxm],y[maxm];//因为重新建图还要用到,所以x,y要拿数组存
int cnt,head[maxn];
int dfn[maxn],low[maxn],co[maxn],v[maxn],val[maxn];//dfn时间戳,low追溯值
int top,st[maxn],siz[maxn],f[maxn],ans,dfncnt,cocnt;//st栈,f记搜
bool vis[maxn];//判断该点在不在栈中
struct node{
int nxt;
int to;
}e[2*maxn];
void add(int from,int to){
e[++cnt].to=to;
e[cnt].nxt=head[from];
head[from]=cnt;
}
void tarjan(int x){
dfn[x]=low[x]=++dfncnt;
st[++top]=x;
vis[x]=1;
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
}
else{
if(vis[y]) low[x]=min(low[x],dfn[y]);//********
}
}
if(low[x]==dfn[x]){
cocnt++;//cocnt记录整张图的强连通分量个数
int now;
do{
now=st[top];
top--;
vis[now]=0;
co[now]=cocnt;//co[now]表示now所在的强连通分量编号
val[cocnt]+=v[now];
}while(now!=x);
}
}
void clear(){
cnt=0;
for(int i=1;i<=m;i++) head[i]=0,e[i].nxt=0,e[i].to=0;
}
void dfs(int x){//在DAG上记忆化搜索
if(f[x]) return ;
f[x]=val[x];
int maxx=0;
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(!f[y]) dfs(y);
maxx=max(maxx,f[y]);
}
f[x]+=maxx;
}
int main(){
read(n),read(m);
for(int i=1;i<=n;i++) read(v[i]);
for(int i=1;i<=m;i++) read(x[i]),read(y[i]),add(x[i],y[i]);//建原图
for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
clear();//把原图清空
for(int i=1;i<=m;i++) if(co[x[i]]!=co[y[i]]) add(co[x[i]],co[y[i]]);//重新建图,如果这条边的两点不在一个强连通分量里,就连上这条边
for(int i=1;i<=cocnt;i++){
if(!f[i]) dfs(i);
ans=max(ans,f[i]);
}
cout<<ans<<endl;
return 0;
}
标签:缩点 stream head read target pen for 模板 http
原文地址:https://www.cnblogs.com/DReamLion/p/14746432.html