Cod sursa(job #236258)

Utilizator MariusMarius Stroe Marius Data 27 decembrie 2008 00:24:07
Problema Componente biconexe Scor Ascuns
Compilator cpp Status done
Runda Marime 4.02 kb
#include <fstream>
#include <iostream>
#include <set>
#include <stack>
#include <vector>
#include <algorithm>

using namespace std;

const char iname[] = "biconex.in";
const char oname[] = "biconex.out";

#define MAXN  100005
#define Min(a, b)  ((a) < (b) ? (a) : (b))

vector <int> adj[MAXN], dfn, low;

vector <vector <int> > C;

stack <pair <int, int> > stk;

void read_in(vector <int>* adj, int &n)
{
    ifstream in(iname);
    int cnt_edges, x, y;

    in >> n >> cnt_edges;
    for (; cnt_edges > 0; -- cnt_edges) {
        in >> x >> y;
        adj[x].push_back(y);
        adj[y].push_back(x);
    }
    in.close();
}

void cache_bc(const int x, const int y)
{
    vector <int> con; int tx, ty;
    do {
        tx = stk.top().first, ty = stk.top().second;
        stk.pop();
        con.push_back(tx), con.push_back(ty);
    }
    while (tx != x || ty != y);
    C.push_back(con);
}

void DF(const int n, const int fn, int number)
{
    vector <int>::iterator it;

    dfn[n] = low[n] = number;
    for (it = adj[n].begin(); it != adj[n].end(); ++ it) {
        if (*it == fn)   continue ;
        if (dfn[*it] == -1) {
            stk.push( make_pair(n, *it) );
            DF(*it, n, number + 1);
            low[n] = Min(low[n], low[*it]);
            if (low[*it] >= dfn[n])
                cache_bc(n, *it);
        }
        else
            low[n] = Min(low[n], dfn[*it]);
    }
}

/* GENERATOR */
set <pair <int, int> > S;
vector <pair <int, int> > V;
vector <int> G[MAXN], used, STK;

void BuildATree(int n, const int diff)
{
    for (STK.push_back(n); STK.size(); ) {
        n = STK.back();
        if (used[n] == 0) {
            used[n] = 1;
            if (STK.size() % diff == 0)
                S.insert( make_pair(n, STK[STK.size() - diff + (rand() % 4)]) );
        }
        int cnt = 0;
        for (int i = 0; i < G[n].size(); ++ i)
            cnt += (used[ G[n][i] ] == 0);
        if (cnt == 0) {     // are descendenti?
            STK.pop_back();
            continue ;
        }
        cnt = (rand() % cnt) + 1;
        int m;
        for (int i = 0; i < G[n].size(); ++ i)
            if ((cnt -= (used[ G[n][i] ] == 0)) == 0) {
                m = G[n][i];
                break ;
            }
        S.insert( make_pair(n, m) );
        STK.push_back(m);
    }
}

void generate(const int n, const int eps, const int diff)
{
    ofstream out(iname);
    srand(unsigned(time(NULL)));

    S.clear();
    for (int i = 1; i <= n; ++ i)
        vector <int>().swap(G[i]);

    for (int i = 1; i < n; ++ i) {
        S.insert( make_pair(i, i + 1) );
        G[i].push_back(i + 1), G[i + 1].push_back(i);
    }
    for (int i = 1; i <= eps; ++ i) {
        int x = (rand() % n) + 1, y = (rand() % n) + 1;
        if (x == y)
            continue ;
        if (x > y)
            swap(x, y);
        if (S.find( make_pair(x, y) ) != S.end())
            continue ;
        S.insert( make_pair(x, y) );
        G[x].push_back(y), G[y].push_back(x);
    }
    used.resize(n + 1), used.assign(used.size(), 0);
    S.clear();
    BuildATree(1, diff);
    while (S.size()) {
        V.push_back(*S.begin());
        S.erase(S.begin());
    }
    random_shuffle(V.begin(), V.end());
    // Scriere in fisier
    out << n << " " << V.size() << "\n";
    for (int i = 0; i < V.size(); ++ i)
        out << V[i].first << " " << V[i].second << "\n";
    out.close();
}

/* MAIN */

int main(void)
{
//  generate(100000, 100000, 64);   return 0;

    int n;
    read_in(adj, n);
    dfn.resize(n + 1), dfn.assign(n + 1, -1);
    low.resize(n + 1);
    DF(1, 0, 0);

    ofstream out(oname);
    out << C.size() << "\n";
    for (int i = 0; i < C.size(); ++ i) {
        sort(C[i].begin(), C[i].end());
        C[i].erase(unique(C[i].begin(), C[i].end()), C[i].end());
        out << "* ";
        for (int j = 0; j < C[i].size(); ++ j)
            out << C[i][j] << " ";
        out << "\n";
    }
    out.close();

    return 0;
}