最少加多少边成为强连通图

#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;
}  
时间: 2024-08-11 01:20:08

最少加多少边成为强连通图的相关文章

给出一张DAG图,问最少加多少条有向边s.t.其强联通?

对于这个问题,可以简化成以下等价(证明略去)版本: 给出一张n个点的DAG图,图中的点出度(简称cd)或者入度(简称rd)为0,问最少加多少有向条边,s.t.其强联通? 定理1:对于一张n个点的DAG图,图中的点出度或者入度为0,最少只需要加n-1条有向边,就可以使其强联通. ·证明:初始状态下,加入第一条边,至多产生一个强联通分量,并且这个强联通分量中只包含两个点(证明略去).为了最小化加入有向边的数目,之后加入的有向边,一定不在这个强联通分量内部(因为它不会使得强联通分量的大小增加).而无论

poj 3352 Road Construction【边双连通求最少加多少条边使图双连通&amp;&amp;缩点】

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10141   Accepted: 5031 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the r

AtCoder Beginner Contest 116 C题 【题意:可以在任意区间【L,R】上加1,求通过最少加1次数得到题目给定的区间】】{思维好题}

C - Grand Garden In a flower bed, there are NN flowers, numbered 1,2,......,N1,2,......,N. Initially, the heights of all flowers are 00. You are given a sequence h={h1,h2,h3,......}h={h1,h2,h3,......} as input. You would like to change the height of

hdoj 3836 Equivalent Sets【scc&amp;&amp;缩点】【求最少加多少条边使图强连通】

Equivalent Sets Time Limit: 12000/4000 MS (Java/Others)    Memory Limit: 104857/104857 K (Java/Others)Total Submission(s): 3568    Accepted Submission(s): 1235 Problem Description To prove two sets A and B are equivalent, we can first prove A is a su

POJ 1236--Network of Schools【scc缩点构图 &amp;&amp; 求scc入度为0的个数 &amp;&amp; 求最少加几条边使图变成强联通】

Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13325   Accepted: 5328 Description A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a li

POJ 1236——Network of Schools——————【加边形成强连通图】

Network of Schools Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 1236 Description A number of schools are connected to a computer network. Agreements have been developed among those schools: e

图之强连通、强连通图、强连通分量 Tarjan算法

强连通分量 简介 在阅读下列内容之前,请务必了解图论基础部分. 强连通的定义是:有向图 G 强连通是指,G 中任意两个结点连通. 强连通分量(Strongly Connected Components,SCC)的定义是:极大的强连通子图. 这里想要介绍的是如何来求强连通分量. Tarjan 算法 Robert E. Tarjan (1948~) 美国人. Tarjan 发明了很多算法结构.光 Tarjan 算法就有很多,比如求各种联通分量的 Tarjan 算法,求 LCA(Lowest Comm

hdu 3836 Equivalent Sets

题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3836 Equivalent Sets Description To prove two sets A and B are equivalent, we can first prove A is a subset of B, and then prove B is a subset of A, so finally we got that these two sets are equivalent.Y

HDU2767 Proving Equivalences

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5742    Accepted Submission(s): 1973 Problem Description Consider the following exercise, found in a generic linear algebra textbook. Let A be an