Cod sursa(job #51089)

Utilizator scapryConstantin Berzan scapry Data 9 aprilie 2007 21:33:36
Problema Count Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.62 kb
#include <assert.h>
#include <stdio.h>
#include <set>
using namespace std;

enum { maxn = 30001 };

int n;
struct ls
{
	int n;
	ls *next;
} *lst[maxn];
set<int> adj[maxn];
int deg[maxn];
bool bad[maxn];
int sorted[maxn];
int tab[maxn], w;
int size, count;

//bkt
int current[5], k, last;

void add(int from, int to)
{
	ls *p = new ls;
	p->n = to;
	p->next = lst[from];
	lst[from] = p;

	deg[from]++;
}

void sort(int left, int right)
{
	assert(left < right);

	int i, j, x = deg[ sorted[(left + right) / 2] ], tmp;

	for(i = left, j = right; i < j; i++, j--) {
		while(deg[ sorted[i] ] < x && i <= j) i++;
		while(deg[ sorted[j] ] > x && j >= i) j--;

		if(i < j) {
			tmp = sorted[i];
			sorted[i] = sorted[j];
			sorted[j] = tmp;
		}
	}

	if(j > left) sort(left, j);
	if(i < right) sort(i, right);
}

bool connected(int a, int b) //TODO: implement with sets (?)
{
	assert(a >= 0 && a < n);
	assert(b >= 0 && b < n);
	assert(a != b);

	assert(!bad[a]);
	assert(!bad[b]);

	//expensive
	/*for(ls *p = lst[a]; p; p = p->next)
		if(p->n == b) {
			assert(adj[a].find(b) != adj[a].end());
			assert(adj[b].find(a) != adj[b].end());
			return true;
		}

	assert(adj[a].find(b) == adj[a].end());
	assert(adj[b].find(a) == adj[b].end());
	return false;*/

	if(adj[a].find(b) != adj[a].end()) return true;
	else return false;
}

void bkt()
{
	if(k > size) {
		size = k;
		count = 1;
	}
	else if(k == size) {
		count++;
	}
	
	//assert(k < 5); //I've isolated the kill to this
	assert(last + 1 >= k);
	if(k) {
		assert(last + 1);
		assert(current[k - 1] == tab[last]);
	}

	int i, saved_last = last;

	for(last++; last < w; last++) {
		current[k] = tab[last];

		for(i = 0; i < k; i++)
			if(!connected(current[k], current[i])) break;

		if(i == k) {
			k++;
			bkt();
			k--;
		}
	}

	last = saved_last;
}

inline void clique()
{
	assert(k == 0);
	last = -1; //because it ++-s it
	bkt();
}

void go()
{	
	int i, node;
	ls *p;

	for(i = 0; i < n; i++) {
		node = sorted[i];
		if(bad[node]) continue;

		tab[0] = node;
		w = 1;
		for(p = lst[node]; p; p = p->next)
			if(!bad[p->n]) tab[w++] = p->n;

		clique();

		bad[node] = true;
	}
}

void build_sets()
{
	int i;
	ls *p;

	for(i = 0; i < n; i++)
		for(p = lst[i]; p; p = p->next)
			adj[i].insert(p->n);
}

int main()
{
	int i, a, b, edges;
	FILE *f = fopen("count.in", "r");
	if(!f) return 1;

	fscanf(f, "%d%d", &n, &edges);
	for(i = 0; i < edges; i++) {
		fscanf(f, "%d%d", &a, &b);
		a--; b--;
		add(a, b);
		add(b, a);
	}

	for(i = 0; i < n; i++)
		sorted[i] = i;
	sort(0, n - 1);

	fclose(f);
	f = fopen("count.out", "w");
	if(!f) return 1;

	build_sets();
	go();

	fprintf(f, "%d %d\n", size, count);
	fclose(f);
	return 0;
}