码迷,mamicode.com
首页 > 其他好文 > 详细

CF949C Data Center Maintenance Tarjan找强连通分量

时间:2018-11-05 16:19:28      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:缩点   add   ==   int   force   include   ORC   限制   codeforce   

题意

  • 给你\(n\)个点,每个点有一个权值\(a_x\),有\(m\)个限制条件形如\(a_x≠a_y\),现在要求你选出\(k(k>0)\)个点使其权值在模\(h\)意义下加\(1\),问最少选多少个点能让限制条件继续满足。

\(Tarjan\)求强连通分量模板题

发现对于每个限制条件,如果\(a_x+1=a_y(mod\ h)\)

那么可以给\(y\)\(x\)连一条有向边

那么最后缩点后找到入度为\(0\)的最小\(scc\)大小即可

Codes

#include <cstdio>
#include <iostream>

using namespace std;

const int N = 1e5 + 10;

int colors, n, m, h, a[N], be[N], size[N], de[N];

namespace Tarjan {
    int from[N << 1], to[N << 1], nxt[N << 1], head[N], e;
    int ins[N], Sta[N], low[N], dfn[N], dfn_cnt, top;

    inline void add(int x, int y) {
        to[++ e] = y; nxt[e] = head[x]; head[x] = e;
    }

    inline void dfs(int x) {
        low[x] = dfn[x] = ++ dfn_cnt, ins[Sta[++ top] = x] = 1;
        for (int i = head[x]; i; i = nxt[i]) {
            if (!dfn[to[i]]) {
                dfs(to[i]);
                low[x] = min(low[to[i]], low[x]);
            }
            else if (ins[to[i]]) 
                low[x] = min(dfn[to[i]], low[x]);
        }
        if (low[x] == dfn[x]) {
            ++ colors; 
            do {
                ++ size[be[Sta[top]] = colors]; 
                ins[Sta[top]] = 0;
            }while (Sta[top --] ^ x);
        }
    }

    inline void Get_Ans() {
        for (int x = 1; x <= n; ++ x) 
            for (int i = head[x]; i; i = nxt[i])
                if (be[x] ^ be[to[i]])
                    ++ de[be[to[i]]];
        int ans = 1e9, id;
        for (int i = 1; i <= colors; ++ i) 
            if (!de[i] && size[i] < ans)
                ans = size[i], id = i;
        printf("%d\n", ans);
        for (int i = 1; i <= n; ++ i) 
            if (be[i] == id) 
                printf("%d ", i);
    }
}

int main() {
#ifdef ylsakioi
    freopen("cf949c.in", "r", stdin);
    freopen("cf949c.out", "w", stdout);
#endif

    scanf("%d%d%d", &n, &m, &h);
    for (int i = 1; i <= n; ++ i) 
        scanf("%d", &a[i]);
    for (int x, y, i = 1; i <= m; ++ i) {
        scanf("%d%d", &x, &y);
        if ((a[x] + 1) % h == a[y]) Tarjan::add(y, x);
        if ((a[y] + 1) % h == a[x]) Tarjan::add(x, y);
    }

    for (int i = 1; i <= n; ++ i) 
        if (!Tarjan::dfn[i])
            Tarjan::dfs(i);
    Tarjan::Get_Ans();

    return 0;
}

CF949C Data Center Maintenance Tarjan找强连通分量

标签:缩点   add   ==   int   force   include   ORC   限制   codeforce   

原文地址:https://www.cnblogs.com/brunch/p/9909343.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!