增加最少的边使有向图变为强连通图

来源:互联网 发布:nginx 多个域名 ssl 编辑:程序博客网 时间:2024/06/09 20:05

http://codeforces.com/contest/22/problem/E


此题是这个问题的简化版本,每个点出度至多为一。先强连通缩点,每个点出度至多为一可以保证从任一个入度为0的点出发只能到达一个出度为0的点按标号从第一个入度为0的点a开始,找到其对应的出度为0的点(缩后)a',再找到第二个入度为0的点b,连边a'->b,...,直到最后一个出度为0的点z‘,连边z’->a,后形成一个“环”。由于图的特殊性,可以保证所有的出度为0的点(缩后)都连了出边,这个"环"上就包含了所有出度 入度为0的点,不难看出,这是强连通图。


至于一般的有向图,假设我们已经强连通缩点得到DAG,设DAG中入度为0的点个数为a,出度为0的点个数为b,则问题的解为max(a, b)。具体方案还没想到。

#include <iostream>#include <cstdlib>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <map>#include <stack>using namespace std;typedef long long LL;typedef unsigned long long ULL;const int MAXN(100010);const int MAXE(100010);template<typename T>bool checkmin(T &a, const T &b){    return b < a? (a = b, true): false;}template<typename T>bool checkmax(T &a, const T &b){    return b > a? (a = b, true): false;}inline int lowb(int i){return i&-i;}int gcd(int a, int b){    while(b){        int t = a%b;        a = b;        b = t;    }    return a;}struct E{    int u, v;    E *next;};struct G{    E *h[MAXN];    E e[MAXE], *r;    void init(int n){        memset(h, 0, sizeof(h[0])*(n+1));        r = e;    }    void add(int u, int v){        r->u = u;        r->v = v;        r->next = h[u];        h[u] = r++;    }} g, g1, g2, g3;stack<int> st;int co[MAXN], rep[MAXN], to[MAXN], ind[MAXN], out[MAXN], cn;bool vis[MAXN];void dfs(int u){    vis[u] = true;    for(E *i = g.h[u]; i; i = i->next)        if(!vis[i->v])            dfs(i->v);    st.push(u);}void dfs1(int u){    co[u] = cn;    for(E *i = g1.h[u]; i; i = i->next)        if(!co[i->v])            dfs1(i->v);}void dfs2(int u, int rt){    vis[u] = true;    bool leaf(true);    for(E *i = g2.h[u]; i; i = i->next){        leaf = false;        if(!vis[i->v]) dfs2(i->v, rt);    }    if(leaf) to[u] = rt;}int main(){    int n, u;    scanf("%d", &n);    g.init(n);    g1.init(n);    for(int i = 1; i <= n; ++i){        scanf("%d", &u);        g.add(i, u);        g1.add(u, i);    }    for(int i = 1; i <= n; ++i)        if(!vis[i])            dfs(i);    while(!st.empty()){        u = st.top();        st.pop();        if(co[u]) continue;        co[u] = ++cn;        rep[cn] = u;        dfs1(u);    }    if(cn == 1){        printf("0\n");        return 0;    }    g2.init(cn);    memset(ind, 0, sizeof(ind[0])*(cn+1));    for(E *i = g.e; i < g.r; ++i)        if(co[i->u] != co[i->v]){            g2.add(co[i->v], co[i->u]);            ++out[co[i->u]];            ++ind[co[i->v]];        }    memset(vis, 0, sizeof(vis[0])*(cn+1));    for(int i = 1; i <= cn; ++i)        if(out[i] == 0)            dfs2(i, i);    int ans = 0, f = 0;    for(int i = 1; i <= cn; ++i)        if(ind[i] == 0){            if(!f) f = i;            ++ans;        }    printf("%d\n", ans);    int l = f;    for(int i = f+1; i <= cn; ++i)        if(ind[i] == 0){            printf("%d %d\n", rep[to[l]], rep[i]);            l = i;        }    printf("%d %d\n", rep[to[l]], rep[f]);    return 0;}


0 0
原创粉丝点击