缩点×2

感觉已经掌握了tarjan的真正思想。。

 1 #include <cstdio>
 2 using namespace std;
 3
 4 const int maxn=1e4+5, maxm=1e5+5;
 5
 6 inline int max(int a, int b) { return a<b?b:a; }
 7 inline int min(int a, int b) { return a<b?a:b; }
 8
 9 class Graph{
10 public:
11     struct Edge{
12         Graph *belong;
13         int to, next;
14         Edge operator ++(){ *this=belong->edge[next]; return *this; }
15         int operator *(){ return to; }
16     };
17     void addedge(int a, int b){
18         Edge &e=edge[++cntedge];
19         e.to=b, e.next=fir[a];
20         fir[a]=cntedge, e.belong=this;
21     }
22     Edge gete(int x) { return edge[fir[x]]; }
23     Edge edge[maxm];
24 private:
25     int cntedge, fir[maxn];
26 };
27
28 int n, m, tail, time, cntscc, ans;
29 int v[maxn], dfn[maxn], low[maxn];
30 int stack[maxn], instack[maxn];
31 int belong[maxn], in[maxn], v_scc[maxn], dp[maxn];
32 Graph g, g_scc;
33
34 void tarjan(int now){
35     dfn[now]=low[now]=++time;
36     stack[++tail]=now, instack[now]=1;
37     int nowson;
38     for (Graph::Edge e=g.gete(now); *e; ++e){
39         nowson=*e;
40         //写在前面比较好,尽管无伤大雅
41         if (instack[nowson])
42             low[now]=min(low[now], dfn[nowson]);
43         if (!dfn[nowson]){
44             tarjan(nowson);
45             low[now]=min(low[now], low[nowson]);
46         }
47     }
48     if (dfn[now]==low[now]){
49         ++cntscc;
50         for (; low[stack[tail]]!=dfn[stack[tail]]; --tail){
51             instack[stack[tail]]=0; //这里忘记了!!
52             belong[stack[tail]]=cntscc;
53             v_scc[cntscc]+=v[stack[tail]];
54         }
55         instack[stack[tail]]=0;
56         belong[stack[tail]]=cntscc;
57         v_scc[cntscc]+=v[stack[tail]];
58         --tail;
59     }
60 }
61
62 void dfs(int now, int par){
63     int nowson;
64     for (Graph::Edge e=g_scc.gete(now); *e; ++e){
65         nowson=*e;
66         if (nowson==par) continue;
67         if (!dp[nowson]) dfs(nowson, now);
68         dp[now]=max(dp[now], dp[nowson]);
69     }
70     dp[now]+=v_scc[now];
71     ans=max(ans, dp[now]);
72 }
73
74 int main(){
75     scanf("%d%d", &n, &m);
76     for (int i=1; i<=n; ++i) scanf("%d", &v[i]);
77     int x, y;
78     for (int i=0; i<m; ++i){ scanf("%d%d", &x, &y); g.addedge(x, y); }
79     for (int i=1; i<=n; ++i)
80         if (!dfn[i]) tarjan(i);
81     for (int i=1; i<=n; ++i)
82         for (Graph::Edge e=g.gete(i); *e; ++e){
83             if (belong[i]!=belong[*e]){
84                 g_scc.addedge(belong[i], belong[*e]);
85                 ++in[belong[*e]];
86             }
87         }
88     for (int i=1; i<=cntscc; ++i)
89         if (!in[i]) dfs(i, 0);
90     printf("%d\n", ans);
91 }
时间: 2024-10-10 02:16:33

缩点×2的相关文章

构建高效可申缩的结果缓存

摘自<<JAVA并发编程实战>> public interface Computable<A, V> { V comput(A arg); } import java.util.concurrent.*; /** * 构建高效可申缩的结果缓存 * <p> * author: shiruiqiang * time: 31/01/2017 23:11 **/ public class Memoizer<A, V> implements Computa

POJ3352(连通分量缩点)

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10352   Accepted: 5140 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the r

HDOJ 5409 CRB and Graph 无向图缩块

无向图缩块后,以n所在的块为根节点,dp找每块中的最大值. 对于每一个桥的答案为两块中的较小的最大值和较小的最大值加1 CRB and Graph Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 113    Accepted Submission(s): 41 Problem Description A connected, undi

UVA-11324 The Largest Clique 【有向图强连通+缩点+DP】

题目链接:https://vjudge.net/problem/UVA-11324 题目大意:给定一张有向图G,求一个结点数最大的结点集,集合中每两个点都至少有一条路径相连(方向任意). 题解: 易知如果一个点被选择,则它所在强连通分量中的其他点也一定要选,如果不选,则其他点也不可选,因此先求出强连通分量,利用缩点创建出另一张有向图G2,每个结点的权值就是该强连通分量的结点数,再DP求解. 代码: 1 #include<bits/stdc++.h> 2 using namespace std;

POJ 2186 Popular Cows(Targin缩点)

传送门 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 31808   Accepted: 12921 Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <=

【BZOJ-1924】所驼门王的宝藏 Tarjan缩点(+拓扑排序) + 拓扑图DP

1924: [Sdoi2010]所驼门王的宝藏 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 787  Solved: 318[Submit][Status][Discuss] Description Input 第一行给出三个正整数 N, R, C. 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室,类型为 Ti.Ti是一个1~3间的整数, 1表示可以传送到第 xi行任意

【BZOJ-1797】Mincut 最小割 最大流 + Tarjan + 缩点

1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1685  Solved: 724[Submit][Status][Discuss] Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci.现在B国想找出一个路径切断方案

【BZOJ1051】1051: [HAOI2006]受欢迎的牛 tarjan求强连通分量+缩点

Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎.你的任务是求出有多少头牛被所有的牛认为是受欢迎的. Input 第一行两个数N,M. 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B) Output 一个数,即有多少头牛被所有的牛认为是受欢迎的. Sample Input 3 3

LightOJ1417 Forwarding Emails(强连通分量+缩点+记忆化搜索)

题目大概是,每个人收到信息后会把信息发给他认识的一个人如此下去,问一开始要把信息发送给谁这样看到信息的人数最多. 首先找出图中的SCC并记录每个SCC里面的点数,如果传到一个SCC,那么里面的人都可以看到信息. 然后SCC缩点后就形成DAG,直接记忆化搜索,d(u)搜索从u点出发开始传最多能传多少人. 最后就是找答案了. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namesp

图论--有向图强连通分量的标记及缩点模板

有向图中在若两点之间可以互相到达,则称这两点强连通,如果一个点集内的所有点都可以互相到达,那么这个点集就是图的一个强连通分量,而我们需要找出有向图中的所有极大强连通分量,于是就用Tarjan算法进行强连通,并将一个连通块缩成一个点,这样就可以形成了一张有向无环图,对解题会很有帮助. 找强连通分量的方法就是 dfs 寻找某个点以及它的后继节点能够到达的最远祖先节点,如果这个最远祖先节点就是进入 dfs 的点,说明所有搜到的后继节点都是在这个强连通分量中,就依次将他们标记为同一个强连通分量. hea