Cod sursa(job #1051024)

Utilizator romircea2010FMI Trifan Mircea Mihai romircea2010 Data 9 decembrie 2013 17:05:18
Problema Count Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.61 kb
#include <fstream>
#include <vector>
#include <set>
#include <queue>
#include <algorithm> /// ?
#define NMax 30010
#define MMax 60010
#define limit 1000000
#define Next ++position == limit?f.read(buffer, limit), position = 0:0
#define ch buffer[position]

using namespace std;

ifstream f ("count.in");
int size, NOD, st[10];
int vecini[10];
int nrvecini;
int sol, nrsol;
int position;
char buffer[limit];
int n, m;
int grad[NMax];
bool viz[NMax], solved[NMax];
vector <int> G[NMax];
set <int> S[NMax];
queue <int> Q;

inline void Read(int &x)
{
    for (; ch < '0' || ch > '9'; Next);
    for (x = 0; '0' <= ch && ch <= '9'; x = x*10 + ch - '0', Next);
}

void Read()
{
    f.read(buffer, limit);
    Read(n), Read(m);
    int i;
    for (i=1; i<=m; ++i)
    {
        int x, y;
        Read(x), Read(y);
        G[x].push_back(y);
        G[y].push_back(x);
        ++grad[x], ++grad[y];
        S[x].insert(y);
        S[y].insert(x);
    }
    f.close();
}

inline bool neighbor(const int A, const int B)
{
    return (S[A].find(B) != S[A].end());
}

inline void back(const int k)
{
    /// combinari de nrvecini luate cate size
    if (k == size + 1)
    {
        int dim = size + 1;
        if (dim == 3)
        {
            /// clica de ordin 3
            if (neighbor(NOD, vecini[st[1]]) && neighbor(NOD, vecini[st[2]]) && neighbor(vecini[st[1]], vecini[st[2]]))
            {
                if (dim == sol)
                    ++nrsol;
                if (dim > sol)
                    sol = dim, nrsol = 1;
            }
        }
        else
        {
            /// clica de ordin 4
            if (neighbor(NOD, vecini[st[1]]) && neighbor(NOD, vecini[st[2]]) && neighbor(NOD, vecini[st[3]]) && neighbor(vecini[st[1]], vecini[st[2]]) && neighbor(vecini[st[1]], vecini[st[3]]) && neighbor(vecini[st[2]], vecini[3]))
            {
                if (dim == sol)
                    ++nrsol;
                if (dim > sol)
                    sol = dim, nrsol = 1;
            }
        }
    }
    else
        for (int i = st[k - 1] + 1; i<=nrvecini; ++i)
        {
            st[k] = i;
            back(k+1);
        }

}

inline void Solve(const int node)
{
    NOD = node;
    solved[node] = true;
    nrvecini = 0;
    for (vector <int>::iterator it = G[node].begin(); it!=G[node].end(); ++it)
    {
        if (!solved[*it])
        {
            vecini[++nrvecini] = *it;
            --grad[*it];
            --grad[node];
            if (grad[*it] < 6 && !viz[*it])
            {
                viz[*it] = true;
                Q.push(*it);
            }
        }

    }
    for (size = 2; size <= 3 && size <= nrvecini; ++size)
    {
        if (size + 1 >= sol)
            back(1); /// comb de nrvecini luate cate size
        /// optimizare??
    }
}

void Solve()
{
    int i;
    for (i=1; i<=n; ++i)
    {
        if (grad[i] < 6)
        {
            Q.push(i);
            viz[i] = true;
        }
    }
    if (m == 0)
    {
        sol = 1;
        nrsol = n;
        return ;
    }
    sol = 2;
    nrsol = m;
    while(!Q.empty())
    {
        int node = Q.front();
        Q.pop();
        /// iau acuma din vecinii nerezeolvati a lui node care vor fi maxim 5 pentru ca de aia am bagat pe node
        /// in coada si incerc sa fac clica maxima cu back, clica care se il cuprinda si pe node
        Solve(node);
    }
}

void Write()
{
    ofstream g ("count.out");
    g<<sol<<" "<<nrsol<<"\n";
    g.close();
}

int main()
{
    Read();
    Solve();
    Write();
    return 0;
}