圖論強連通專題:POJ1236

題目描述:

有一些學校通過單向網絡連通,求出下面兩個問題:

1.至少在多少個學校拷貝一個軟件,使得這個軟件能通過網絡傳遍所有學校。

2.至少加多少條單向網絡,使得任意在一個學校拷貝軟件,就能使得這個軟件通過網絡傳遍所有學校。

大致思路:

如果直接深搜的話複雜度NM肯定超時,所以先用強連通縮點,然後找出入度爲0得點就是第一個問題的答案,而第二個問題就是加多少條邊,使得圖成爲強連通。這個答案就是入度0和出度0點個數中的最大值。

代碼:

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 100 + 10;
vector<int> G[maxn];
vector<int> rG[maxn];
int n;
vector<int> vs;
bool used[maxn];
int cmp[maxn];
bool g[maxn][maxn];

void add_edge(int from, int to) {
    G[from].push_back(to);
    rG[to].push_back(from);
}

void dfs(int v) {
    used[v] = true;
    for (int i = 0; i < G[v].size(); i++) {
        if (!used[G[v][i]]) dfs(G[v][i]);
    }
    vs.push_back(v);
 }

 void rdfs(int v, int k) {
    used[v] = true;
    cmp[v] = k;
    for (int i = 0; i < rG[v].size(); i++) {
        if (!used[rG[v][i]]) rdfs(rG[v][i], k);
    }
 }

 int scc() {
    memset(used,0,sizeof(used));
    vs.clear();
    for (int i = 1; i <= n; i++) {
        if (!used[i]) dfs(i);
    }
    memset(used,0,sizeof(used));
    int k = 0;
    for (int i = vs.size() - 1; i >=0; i--) {
        if (!used[vs[i]]) rdfs(vs[i], k++);
    }
    return k;
 }

 int main() {
    while (cin>>n) {
        for (int i = 1; i <= n; i++) {
            int tmp;
            while (cin>>tmp,tmp) {
                add_edge(i,tmp);
            }
        }
        int nV = scc();
        int v_in[maxn],v_out[maxn];
        memset(v_in,0,sizeof(v_in));
        memset(v_out,0,sizeof(v_out));
        memset(g,0,sizeof(g));
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < G[i].size(); j++) {
                if (cmp[i] != cmp[G[i][j]]) {
                    v_in[cmp[G[i][j]]]++;
                    v_out[cmp[i]]++;
                }
            }
        }
        int zi = 0, zo = 0;
        for (int i = 0; i < nV; i++) {
            if (!v_in[i]) zi++;
            if (!v_out[i]) zo++;
        }
        if (nV == 1) {
            cout<<"1"<<endl<<"0"<<endl;
        }
        else {
            cout<<zi<<endl;
            cout<<max(zi,zo)<<endl;
        }
     }
 }


發佈了90 篇原創文章 · 獲贊 0 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章