缩点

缩点

预备知识-强连通分量

缩点就是在求完强连通分量后新建一个结构体,将每一个强连通分量看做一个新的点,建一个新的图。
P3387

#include <iostream>
#include <cstdio>
using namespace std;
long long read(){
	long long x = 0; int f = 0; char c = getchar();
	while(c < '0' || c > '9') f |= c == '-', c = getchar();
	while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
	return f? -x:x;
}

int n, m, w[10004];
struct szh{
	int next, x, y;
}a[100005], b[100005];
int hd[10004], cnt, dfn[10004], low[10004], s[10004], top;
int in[10004], F[10004], ans, H[10004], d[10004];
bool vis[10004];
inline void add(int x, int y){
	a[++cnt].x = x = read(),a[cnt].y = y = read(),a[cnt].next = hd[x], hd[x] = cnt;
}
void Tarjan(int u){
	dfn[u] = low[u] = ++cnt, vis[u] = 1, s[++top] = u;
	for(int i = hd[u], v; v = a[i].y, i; i = a[i].next)
		if(!dfn[v]){
			Tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else if(vis[v]) low[u] = min(low[u], dfn[v]);
	if(low[u] == dfn[u])
		while(int k = s[top--]){
			F[k] = u, vis[k] = 0;
			if(k == u) break;
			w[u] += w[k];
		}
}
int main(){
	n = read();  m = read();
	for (int i = 1; i <= n ;++i) w[i] = read();
	for (int i = 1, x, y; i <= m; ++i) add(x,y);
	cnt = 0;
	for(int i = 1; i <= n; ++i) if(!dfn[i]) Tarjan(i);
	cnt = 0;
	for(int i = 1; i <= m; ++i){
		int x = F[a[i].x], y = F[a[i].y];
		if(x != y) b[++cnt].x = x, b[cnt].y = y, b[cnt].next = H[x], H[x] = cnt, in[y]++;
	}
	top = 0;
	for(int i = 1; i<= n; ++i)
		if(F[i] == i && !in[i]) s[++top] = i, d[i] = w[i];
	while(top){
		int u = s[top--];
		for(int i = H[u], v; v = b[i].y, i; i = b[i].next){
			d[v] = max(d[v], d[u] + w[v]);
			if(--in[v] == 0) s[++top] = v;
		}
	}
	for(int i = 1; i <= n; ++i) ans = max(ans,d[i]);
	printf("%d\n", ans);
	return 0;
}

欢迎指正评论O(∩_∩)O~~

posted @ 2018-11-01 14:41  Kylin_Seven  阅读(342)  评论(0编辑  收藏  举报