P3387 【模板】缩点
2017-11-25 19:55
232 查看
P3387 【模板】缩点
题目背景
缩点+DP
题目描述
给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。
允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。
输入输出格式
输入格式:
第一行,n,m
第二行,n个整数,依次代表点权
第三至m+2行,每行两个整数u,v,表示u->v有一条有向边
输出格式:
共一行,最大的点权之和。
输入输出样例
输入样例#1: 复制2 2 1 1 1 2 2 1输出样例#1: 复制
2
说明
n<=10^4,m<=10^5,|点权|<=1000 算法:Tarjan缩点+DAGdp
分析
缩点成有点无环图(树),然后拓扑+dp
code
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<cstdlib> using namespace std; const int N = 20100; const int M = 200100; struct Edge{ int to,nxt; }e[M],s[M]; // 不要混用!!! int head ,dfn ,low ,st ,bel ,h ; int ru ,q[1000000],L,R,w ,sw ,ans ; bool vis ; int cnt,tn,tot,top,tot1; inline char nc() { static char buf[100000],*p1 = buf,*p2 = buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF : *p1++; } inline int read() { int x = 0,f = 1;char ch = nc(); for (; ch<'0'||ch>'9'; ch = nc()) if (ch=='-') f = -1; for (; ch>='0'&&ch<='9'; ch = nc()) x = x*10+ch-'0'; return x * f; } inline void add_edge(int u,int v) { e[++tot].to = v,e[tot].nxt = head[u],head[u] = tot; } inline void add(int u,int v) { s[++tot1].to = v,s[tot1].nxt = h[u],h[u] = tot1; // 不要写成e } void tarjan(int u) { dfn[u] = low[u] = ++tn; st[++top] = u; vis[u] = true; 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 (vis[v]) low[u] = min(low[u],dfn[v]); } if (low[u]==dfn[u]) { ++cnt; do { vis[st[top]] = false; bel[st[top]] = cnt; sw[cnt] += w[st[top]]; top--; } while (st[top+1] != u); } } int main() { int n = read(),m = read(); for (int i=1; i<=n; ++i) w[i] = read(); for (int i=1; i<=m; ++i) { add_edge(read(),read()); } for (int i=1; i<=n; ++i) if (!dfn[i]) tarjan(i); for (int u=1; u<=n; ++u) { for (int i=head[u]; i; i=e[i].nxt) { int v = e[i].to; if (bel[u]!=bel[v]) add(bel[u],bel[v]),ru[bel[v]]++; } } L = 1,R = 0; for (int i=1; i<=cnt; ++i) { if (!ru[i]) q[++R] = i,ans[i] = sw[i]; } while (L <= R) { int u = q[L++]; for (int i=h[u]; i; i=s[i].nxt) { int v = s[i].to; ans[v] = max(ans[u]+sw[v],ans[v]); ru[v] --; if (ru[v]==0) q[++R] = v; // 拓扑!!!不是bfs } } int mx = 0; for (int i=1; i<=cnt; ++i) { mx = max(mx,ans[i]); } printf("%d",mx); return 0; }
相关文章推荐
- 【模板】缩点 洛谷p3387
- P3387 【模板】缩点
- 洛谷 P3387 【模板】缩点
- Tarjan 缩点模板(洛谷P3387)
- 洛谷 P3387 【模板】缩点
- Tarjan+topsort(DP)【P3387】 [模板]缩点
- 强联通分量缩点模板
- luoguP3387 【模板】缩点
- 连通分量模板:tarjan: 求割点 && 桥 && 缩点 && 强连通分量 && 双连通分量 && LCA(近期公共祖先)
- 强连通分量缩点的模板
- 图论--有向图强连通分量的标记及缩点模板
- Tarjan缩点模板
- 有向图tarjan 求桥 + 求SCC以及里面的点和它的入度 +缩点 模板 【总结】
- 【模板】Tarjan 缩点 + 最长路
- 浅谈Tarjan缩点(分析+模板)
- tarjan模板(缩点,求有向图强连通分量)
- Tarjan 缩点(P3387)
- dijkstra模板+ 缩点-bupt新oj-187- Find the Fastest Server
- 强连通分量模板+DAGdp 洛谷P3387
- 有向图tarjan 求桥 + 求SCC以及里面的点和它的入度 +缩点 模板 【总结】