Luogu3387 缩点

缩点+DAG上DP

缩完点跑一遍拓扑,无后效性。真你妈神烦,调不过去。

艹调了一个小时就因为一个入度加错点了。我真傻叉。

CODE:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
#define maxn 10001
#define maxm 100001
int n, m, low[maxn], dfn[maxn], scc[maxn];
int tot, col, ans, top, cnt;
struct edge{
	int nxt, to;
}e[maxm];
int st[maxn], dis[maxn], w[maxn], head[maxn], val[maxn], ind[maxn];
inline int read(){
	int f=1, x=0;
	char ch=getchar();
	for(;!isdigit(ch); ch=getchar()) if(ch=='-') f=-1;
	for(; isdigit(ch); ch=getchar()) x=x*10+ch-48;
	return x*f;
}
void add(int u, int v){
	e[++tot].nxt=head[u];
	e[tot].to=v;
	head[u]=tot;
}
void tarjan(int u){
	dfn[u]=low[u]=++cnt;
	st[++top]=u;
	for(int i=head[u]; i; i=e[i].nxt){
		int v=e[i].to;
		if(!dfn[v]){
			tarjan(v);
			low[u]=min(low[u], low[v]);
		}
		else if(!scc[v])
			low[u]=min(low[u], dfn[v]);
	}
	if(low[u]==dfn[u]){
		scc[u]=++col;
		w[col]+=val[u];
		while(st[top]!=u){
			scc[st[top]]=col;
			w[col]+=val[st[top--]];
		}
		top--;
	}
}
void topo(){
	queue<int>q;
	for(int i=1; i<=col; i++)
		if(!ind[i]){
			q.push(i);
			dis[i]=w[i];
		}
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=head[u]; i; i=e[i].nxt){
			int v=e[i].to;
			dis[v]=max(dis[v], dis[u]+w[v]);
			ind[v]--;
			if(!ind[v]) q.push(v);
		}
	}
	ans=0;
	for(int i=1; i<=n; i++)
		ans=max(ans, dis[i]);
}
int x[maxm], y[maxm];
int main(){
	n=read(), m=read();
	for(int i=1; i<=n; i++) val[i]=read();
	for(int i=1; i<=m; i++){
		x[i]=read(), y[i]=read();
		add(x[i], y[i]);
	}
	for(int i=1; i<=n; i++)
		if(!dfn[i])tarjan(i);
	memset(e, 0, sizeof(e));
	memset(head, 0, sizeof(head));
	for(int i=1; i<=m; i++)
		if(scc[x[i]]!=scc[y[i]])
			add(scc[x[i]], scc[y[i]]), ind[scc[y[i]]]++;
	topo();
	printf("%d", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/pushinl/p/9911914.html