Cod sursa(job #1047141)

Utilizator toranagahVlad Badelita toranagah Data 3 decembrie 2013 22:57:57
Problema Count Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.35 kb
#include <algorithm>
#include <fstream>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
using namespace std;

ifstream fin("count.in");
ofstream fout("count.out");

const int MAX_N = 30100;
const int MAX_M = 60100;

int N, M;
pair<int, int> edges[MAX_M];
vector<int> graph[MAX_N];
bool removed_edge[MAX_M];
int node_degree[MAX_N];
pair<int, int> max_clique;

struct set_cmp {
    bool operator() (const int &lhs, const int &rhs) const {
        if (node_degree[lhs] == node_degree[rhs]) return lhs < rhs;
        return (node_degree[lhs] < node_degree[rhs]);
    }
};
set<int, set_cmp> nodes;

void read_input();
void solve();
void print_output();
pair<int, int> find_max_clique();
pair<int, int> compute_clique(int node);
bool adjacent(int a, int b);
int other(int edge, int node);
void update_pair(pair<int, int> &p, int val);


int main() {
    read_input();
    solve();
    print_output();
    return 0;
}

void read_input() {
    fin >> N >> M;
    for (int i = 1; i <= M; ++i) {
        fin >> edges[i].first;
        fin >> edges[i].second;

        graph[edges[i].first].push_back(i);
        graph[edges[i].second].push_back(i);
    }
}

void solve() {
    for (int i = 1; i <= N; ++i) {
        node_degree[i] = graph[i].size();
        nodes.insert(i);
    }

    max_clique = find_max_clique();
}

void print_output() {
    fout << max_clique.first << ' ' << max_clique.second;
}

pair<int, int> find_max_clique() {
    pair<int, int> result = make_pair(0, 0);

    for (int step = 1; step <= N; ++step) {
        int node = *nodes.begin();
        pair<int, int> clique = compute_clique(node);

        if (clique.first > result.first) {
            result = clique;
        } else if (clique.first == result.first) {
            result.second += clique.second;
        }

        nodes.erase(nodes.begin());
        for (auto x: graph[node]) {
            if (removed_edge[x]) continue;
            int neighbour = other(x, node);
            nodes.erase(nodes.find(neighbour));

            removed_edge[x] = true;
            node_degree[neighbour] -= 1;

            nodes.insert(neighbour);
        }
    }
    return result;
}

pair<int, int> compute_clique(int node) {
    pair<int, int> result = make_pair(1, 1);
    int n = graph[node].size();

    for (int a = 0; a < n; ++a) {
        if (removed_edge[graph[node][a]]) continue;
        update_pair(result, 2);

        for (int b = a + 1; b < n; ++b) {
            if (removed_edge[graph[node][b]]) continue;
            if (adjacent(other(graph[node][a], node), other(graph[node][b], node))) {
                update_pair(result, 3);

                for (int c = b + 1; c < n; ++c) {
                    if (removed_edge[graph[node][c]]) continue;
                    if (adjacent(other(graph[node][b], node), other(graph[node][c], node))) {
                        update_pair(result, 4);
                    }
                }
            }
        }
    }
    return result;
}

inline void update_pair(pair<int, int> &p, int val) {
    if (val > p.first) {
        p = make_pair(val, 1);
    } else if (val == p.first) {
        p.second += 1;
    }
}

inline bool adjacent(int a, int b) {
    for (auto x: graph[a]) {
        if (removed_edge[x]) continue;
        if (other(x, a) == b) return true;
    }
    return false;
}

inline int other(int edge, int node) {
    return edges[edge].first + edges[edge].second - node;
}