首页 > 其他分享 >洛谷P2002 消息扩散(tarjan缩点)

洛谷P2002 消息扩散(tarjan缩点)

时间:2022-09-06 16:23:34浏览次数:68  
标签:缩点 P2002 tarjan int void scc low include

题目链接:https://www.luogu.com.cn/problem/P2002

思路:由于图中每个强连通分量(scc)中的点是可以互相到达的,所以我们可以用tarjan求图中scc,然后将所有scc缩点,最后求缩点之后图中入度为0的点的个数就是答案。

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<vector>
  4 #include<map>
  5 #include<queue>
  6 #include<set>
  7 #include<algorithm>
  8 #include<stack>
  9 #include<cmath>
 10 #include<cstring>
 11 #include<string>
 12 using namespace std;
 13 #define gc getchar()
 14 #define rd(x) read(x)
 15 #define el '\n'
 16 #define rep(i, a, n) for(int i = (a); i <= n; ++i)
 17 #define per(i, a, n) for(int i = (a); i >= n; --i)
 18 using ll = long long;
 19 using db = double;
 20 using ldb = long double;
 21 const int mod = 1e9 + 7;
 22 const int inf = 0x3f3f3f3f;
 23 const int N = 100000 + 10;
 24 
 25 template <typename _T>
 26 inline void read(_T& f) {
 27     f = 0; _T fu = 1; char c = gc;
 28     while (c < '0' || c > '9') { if (c == '-') { fu = -1; } c = gc; }
 29     while (c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = gc; }
 30     f *= fu;
 31 }
 32 
 33 template <typename T>
 34 void print(T x) {
 35     if (x < 0) putchar('-'), x = -x;
 36     if (x < 10) putchar(x + 48);
 37     else print(x / 10), putchar(x % 10 + 48);
 38 }
 39 
 40 template <typename T>
 41 void print(T x, char t) {
 42     print(x); putchar(t);
 43 }
 44 
 45 int dfn[N], low[N], ins[N], scc[N], in[N];
 46 int dfncnt, scccnt;
 47 stack<int>st;
 48 vector<int>G[N];
 49 vector<int>DAG[N];
 50 
 51 int n, m;
 52 int pmax;
 53 
 54 void tarjan(int u) {
 55     dfn[u] = ++dfncnt;
 56     low[u] = dfncnt;
 57     st.push(u);
 58     ins[u] = true;
 59     for (int i = 0; i < G[u].size(); i++) {
 60         int v = G[u][i];
 61         if (!dfn[v]) {
 62             tarjan(v);
 63             low[u] = min(low[u], low[v]);
 64         }
 65         else if (ins[v]) {
 66             low[u] = min(low[u], dfn[v]);
 67         }
 68     }
 69     if (dfn[u] == low[u]) {
 70         int v;
 71         ++scccnt;
 72         pmax = max(pmax, scccnt);
 73         do {
 74             v = st.top();
 75             st.pop();
 76             ins[v] = false;
 77             scc[v] = scccnt;
 78         } while (u != v);
 79     }
 80 }
 81 
 82 void getdag() {
 83     for (int i = 1; i <= n; i++) {
 84         if (!dfn[i]) {
 85             tarjan(i);
 86         }
 87     }
 88     for (int u = 1; u <= n; u++) {
 89         for (int j = 0; j < G[u].size(); j++) {
 90             int v = G[u][j];
 91             if (scc[u] != scc[v]) {
 92                 DAG[scc[u]].push_back(scc[v]);
 93                 in[scc[v]]++;
 94             }
 95         }
 96     }
 97 }
 98 
 99 int main() {
100 
101     ios::sync_with_stdio(false);
102     cin.tie(0), cout.tie(0);
103     //int n, m;
104     cin >> n >> m;
105     for (int i = 1; i <= m; i++) {
106         int u, v;
107         cin >> u >> v;
108         G[u].push_back(v);
109     }
110     getdag();
111     int ans = 0;
112     for (int i = 1; i <= pmax; i++) {
113         if (!in[i]) ans++;
114     }
115     cout << ans << el;
116 
117     return 0;
118 }

 

 

标签:缩点,P2002,tarjan,int,void,scc,low,include
From: https://www.cnblogs.com/wabi/p/16662221.html

相关文章

  • 信息学奥赛一本通 1314:【例3.6】过河卒(Noip2002)
    时间限制:1000ms      内存限制:65536KB提交数:26367   通过数:11410【题目描述】棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下......
  • 洛谷 P1036 [NOIP2002 普及组] 选数(dfs)
    https://www.luogu.com.cn/problem/P1036题目大意:从给定的n个数中选出m个求和,结果是一个素数的情况有多少种?输入43371219输出1这个题目的代码是根据Acwing中......
  • 缩点后 spfa求最长路(不知道为什么top+dp做不了)
    #include<queue>#include<cstdio>#include<cstring>#defineN500005usingnamespacestd;structedge{intto,val,next;}e[N];intm,n,p,s,cnt,g[N],u[N],v......
  • P1002 [NOIP2002 普及组] 过河卒 题解
    题目:[NOIP2002普及组]过河卒题目描述棋盘上\(A\)点有一个过河卒,需要走到目标\(B\)点。卒行走的规则:可以向下、或者向右。同时在棋盘上\(C\)点有一个对方的马,该......
  • tarjan算法求强连通分量
    \(tarjan\)算法求强连通分量\(tarjan\)算法简介我在这篇博客中讲过\(tarjan\)算法的简介和求割点与桥,就不再讲述。强连通分量强连通图是指一个有向图内任意两点都能互......
  • [NOIP2002 普及组] 选数
    题目链接:https://www.luogu.com.cn/problem/P1036试题分析:题目要求从n个数中任选k个数相加,求有多少种和为素数的情况。这道题我们运用的主要是深搜,其次还要写一个判断素数......
  • tarjan
    changelog:新建此随笔,还有一些东西未完工。https://www.youtube.com/watch?v=TyWtx7q2D7Y有向图的DFS生成树主要有4种边(不一定全部出现):树边(treeedge):示意图中以黑色......
  • 洛谷P1037 [NOIP2002 普及组] 产生数
    排列组合QWQ当我第一眼看见这到题,K才15???,于是默默的打出了暴搜。以我这么高(la)超(ji)的水平,当然是TLE.....对着屏幕一呆,70行代码。。。。步入正题:再打深搜,那是不可......
  • [NOIP2002 提高组] 均分纸牌
    题目链接:https://www.luogu.com.cn/problem/P1031试题分析:首先分析样例:输入样例后,我们要先求出平均值,进而求出与平均值的差值: 我们能够得到三次移动:1.  7向右-4变......