zoukankan      html  css  js  c++  java
  • 题解【CF999E】Reachability from the Capital

    题面

    容易发现一个强连通分量内的点可以互相到达,因此首都最多向每一个强连通分量内连一条边。

    于是缩点,原图变成了一个 DAG。

    易知只需要向每一个入度为 0 的强连通分量连一条边,这个可以直接统计。

    #include <bits/stdc++.h>
    #define DEBUG fprintf(stderr, "Passing [%s] line %d
    ", __FUNCTION__, __LINE__)
    #define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
    
    using namespace std;
    
    typedef long long LL;
    typedef pair <int, int> PII;
    typedef pair <int, PII> PIII;
    
    template <typename T>
    inline T gi()
    {
    	T f = 1, x = 0; char c = getchar();
    	while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return f * x;
    }
    
    const int INF = 0x3f3f3f3f, N = 5003, M = N << 1;
    
    int n, m, s;
    int tot, head[N], ver[M], nxt[M];
    int dfn[N], low[N], tim, stk[N], tp, id[N], scc_cnt;
    bool in_stk[N];
    int du[N];
    
    inline void add(int u, int v) {ver[++tot] = v, nxt[tot] = head[u], head[u] = tot;}
    
    void Tarjan(int u)
    {
    	dfn[u] = low[u] = ++tim, stk[++tp] = u, in_stk[u] = true;
    	for (int i = head[u]; i; i = nxt[i])
    	{
    		int v = ver[i];
    		if (!dfn[v])
    		{
    			Tarjan(v);
    			low[u] = min(low[u], low[v]);
    		}
    		else if (in_stk[v]) low[u] = min(low[u], dfn[v]);
    	}
    	if (dfn[u] == low[u])
    	{
    		++scc_cnt;
    		int y = -1;
    		do
    		{
    			y = stk[tp--];
    			id[y] = scc_cnt;
    			in_stk[y] = false;
    		} while (y != u);
    	}
    }
    
    int main()
    {
    //	File("");
    	n = gi <int> (), m = gi <int> (), s = gi <int> ();
    	for (int i = 1; i <= m; i+=1)
    	{
    		int u = gi <int> (), v = gi <int> ();
    		add(u, v);
    	}
    	for (int i = 1; i <= n; i+=1) if (!dfn[i]) Tarjan(i);
    	for (int u = 1; u <= n; u+=1)
    		for (int i = head[u]; i; i = nxt[i])
    		{
    			int v = ver[i];
    			if (id[u] != id[v]) ++du[id[v]];
    		}
    	int cnt = 0;
    	for (int i = 1; i <= scc_cnt; i+=1) cnt += (du[i] == 0);
    	printf("%d
    ", cnt - (du[id[s]] == 0));
    	return 0;
    }
    
  • 相关阅读:
    Codeforces Round #555 (Div. 3) A B C1(很水的题目)
    蓝桥杯国赛之阶乘位数
    POJ-1258 Agri-Net(最小生成树)
    昂贵的聘礼(枚举区间+最短路)
    地斗主(矩阵快速幂)
    救救兔子(二分)
    shell编程之sed编辑器&gawk程序
    typedef&nbsp;struct与struct的区别
    iOS内存管理编程指南
    Object&nbsp;c&nbsp;基础知识
  • 原文地址:https://www.cnblogs.com/xsl19/p/14084913.html
Copyright © 2011-2022 走看看