算法题 洛谷P3387
原创洛谷 P3387 [模板]收缩点[模板]收缩点
Description
-
给定一个n个点m一个条带边有向图,其中每个点都有一个权重,找到一条路径,使得该路径所经过的点的权重之和最大化。你只需要找到这个重量的总和。
允许在一条边或一个点上进行多次走刀,但是,对于重复走刀,仅计算一次权重。
Input
-
第一行,n,m
第二行,n按顺序,这些整数表示点的幂
第三至m+2它还可以用于服务器领域。它也可以在服务器区域使用。它还可以用于服务器领域。它还可以用于服务器部门。u,v,表示u->v有方向的边,有有向的边
Output
- 命令,然后输入服务器连接密码以登录到远程服务器而不会出现任何问题。从现在起,我们可以在本地计算机上操作远程服务器。
Sample Input
2 2
1 1
1 2
2 1
Sample Output
2
Data Size
- n<=10^4,m<=10^5,0<=点权<=1000
题解:
- 一道tarjan模板
- 我们的想法是使用收缩点来转换DAG跑dp
- 我的代码太长我的代码太长我的代码太长
-
关于tarjan博客: 链接
include
include
include
include
include
define maxn 100005
using namespace std;
struct Obj {int w, num;} obj[maxn]; struct E {int next, to;} e[maxn], edge[maxn]; int n, m, num, dex, tot, num_edge, ans; int h[maxn], dfn[maxn], low[maxn], val[maxn], belong[maxn], head[maxn]; int uu[maxn], vv[maxn], in[maxn], seq[maxn], dp[maxn]; bool vis[maxn]; stack
stk; int read() { int x = 0; char c = getchar(); while(c < 0 || c > 9) c = getchar(); while(c >= 0 && c <= 9) {x = x * 10 + c - 0; c = getchar();} return x; }
void add(int u, int v) { e[++num].next = h[u]; e[num].to = v; h[u] = num; }
void tarjan(int x) { dfn[x] = low[x] = ++dex; stk.push(x), vis[x] = 1; for(int i = h[x]; i != 0; i = e[i].next) { int now = e[i].to; if(!dfn[now]) tarjan(now), low[x] = min(low[now], low[x]); else if(vis[now]) low[x] = min(low[x], dfn[now]); } if(low[x] == dfn[x]) { tot++, obj[tot].num = tot; while(1) { int now = stk.top(); obj[tot].w += val[now]; belong[now] = tot; stk.pop(); if(now == x) break; } } }
void add_edge(int from, int to) { edge[++num_edge].next = head[from]; edge[num_edge].to = to; head[from] = num_edge; }
void topsort() { queue
que; for(int i = 1; i <= tot; i++) if(!in[i]) que.push(i), dp[i] = obj[i].w; while(!que.empty()) { int now = que.front(); ans = max(ans, dp[now]); que.pop(); for(int i = head[now]; i != 0; i = edge[i].next) { dp[edge[i].to] = max(dp[edge[i].to], dp[now] + obj[edge[i].to].w); in[edge[i].to]--; if(!in[edge[i].to]) que.push(edge[i].to); } } } int main() { cin >> n >> m; for(int i = 1; i <= n; i++) val[i] = read(); for(int i = 1; i <= m; i++) { int u = read(), v = read(); uu[i] = u, vv[i] = v; add(u, v); } for(int i = 1; i <= n; i++) if(!dfn[i]) tarjan(i); for(int i = 1; i <= m; i++) if(belong[uu[i]] != belong[vv[i]]) add_edge(belong[uu[i]], belong[vv[i]]), in[belong[vv[i]]]++; topsort(); cout << ans; return 0; }
转载于:https://www.cnblogs.com/BigYellowDog/p/11205289.html
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除
itfan123
