[Codeforces Round #286 DIV1B (CF506B)] Mr. Kitayuta's Technology

题意

n 个点互不相连,现有m个单向连通性要求,问最少需要多少条单向边。

题解

m 个连通性要求当做双向边建并查集找到所有的连通块,对每个集合,如果不存在环,这个连通块的答案是|V|1,否则这个连通块的答案是 |V|

代码

// by ztx

#include <cstdio>
#include <algorithm>

#define  maxn  100010LL

int e[2][maxn], star[maxn] = {0}, tote = 0;
#define  to(p) e[0][p]
#define  nxt(p) e[1][p]
inline void AddEdge(int u,int v) {
    tote ++ , to(tote) = v, nxt(tote) = star[u], star[u] = tote;
}

int fa[maxn] = {0};
inline int GetAnc(int u) { return fa[u] ? fa[u]=GetAnc(fa[u]) : u; }
inline void Union(int u,int v) {
    u = GetAnc(u), v = GetAnc(v);
    if (u != v) fa[u] = v;
}

int ind[maxn] = {0}, poi[maxn];
inline bool cmp(const int&a,const int&b) {
    return fa[a]==fa[b] ? ind[a] < ind[b] : fa[a] < fa[b];
}

int sta[maxn], top;
inline bool Circle(int L,int R) {
    int i, u, p;
    top = 0;
    for (i = L; i <= R; i ++ )
        if (ind[poi[i]] == 0) sta[++top] = poi[i];
        else break;
    while (top) {
        u = sta[top--];
        for (p = star[u]; p; p=nxt(p))
            if ((--ind[to(p)]) == 0) sta[++top] = to(p);
    }
    for (i = R; i >= L; i -- ) if (ind[poi[i]] > 0) return true;
    return false;
}

int n, m;

int main() {
    int i, u, v, ans, last;
    scanf("%d%d", &n, &m);
    for (i = 1; i <= m; i ++ ) {
        scanf("%d%d", &u, &v);
        AddEdge(u,v), Union(u,v), ind[v] ++ ;
    }
    for (i = 1; i <= n; i ++ )
        GetAnc(i), poi[i] = i;
    for (i = 1; i <= n; i ++ )
        if (!fa[i]) fa[i] = i;
    std::sort(poi+1,poi+n+1,cmp);
    ans = 0, last = 1;
    poi[n+1] = n+1, fa[n+1] = -1;
    for (i = 1; i <= n; i ++ )
        if (fa[poi[i]] != fa[poi[i+1]]) {
            if (Circle(last,i)) ans += i-last+1;
            else ans += i-last;
            last = i+1;
        }
    printf("%d\n", ans);
//while(1);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值