結果

問題 No.2987 Colorful University of Tree
ユーザー 👑 ygussany
提出日時 2024-12-12 02:19:44
言語 C
(gcc 13.3.0)
結果
AC  
実行時間 594 ms / 5,000 ms
コード長 8,558 bytes
コンパイル時間 518 ms
コンパイル使用メモリ 39,136 KB
実行使用メモリ 52,304 KB
最終ジャッジ日時 2024-12-12 02:20:03
合計ジャッジ時間 19,196 ms
ジャッジサーバーID
(参考情報)
judge2 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 41
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <stdio.h>
#include <stdlib.h>

#define MT_N 624
#define MT_M 397
#define MT_MATRIX_A 0x9908b0dfUL
#define MT_UPPER_MASK 0x80000000UL
#define MT_LOWER_MASK 0x7fffffffUL

static unsigned int mt[MT_N];
static int mti = MT_N + 1;

void init_genrand(unsigned int s)
{
    mt[0] = s & 0xffffffffUL;
    for (mti = 1; mti < MT_N; mti++) {
        mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); 
        mt[mti] &= 0xffffffffUL;
    }
}

unsigned int genrand()
{
    unsigned int y;
    static unsigned int mag01[2] = {0x0UL, MT_MATRIX_A};

    if (mti >= MT_N) {
        int kk;
        if (mti == MT_N + 1) init_genrand(5489UL);
		
        for (kk = 0; kk < MT_N - MT_M; kk++) {
            y = (mt[kk] & MT_UPPER_MASK) | (mt[kk+1] & MT_LOWER_MASK);
            mt[kk] = mt[kk+MT_M] ^ (y >> 1) ^ mag01[y&0x1UL];
        }
        for (; kk < MT_N - 1; kk++) {
            y = (mt[kk] & MT_UPPER_MASK) | (mt[kk+1] & MT_LOWER_MASK);
            mt[kk] = mt[kk+(MT_M-MT_N)] ^ (y >> 1) ^ mag01[y&0x1UL];
        }
        y = (mt[MT_N-1] & MT_UPPER_MASK) | (mt[0] & MT_LOWER_MASK);
        mt[MT_N-1] = mt[MT_M-1] ^ (y >> 1) ^ mag01[y&0x1UL];

        mti = 0;
    }
  
    y = mt[mti++];

    y ^= (y >> 11);
    y ^= (y << 7) & 0x9d2c5680UL;
    y ^= (y << 15) & 0xefc60000UL;
    y ^= (y >> 18);

    return y;
}

void shuffle_permutation(int N, int p[], int K)
{
	int i, j;
	while (K--) {
		i = genrand() % N + 1;
		j = genrand() % N + 1;
		if (i != j) {
			p[i] ^= p[j];
			p[j] ^= p[i];
			p[i] ^= p[j];
		}
	}
}

void chmax(int *a, int b)
{
	if (*a < b) *a = b;
}

typedef struct {
	int key, id;
} data;

typedef struct {
	data obj[200001];
	int size;
} max_heap;

void push(max_heap* h, data x)
{
	int i = ++(h->size), j = i >> 1;
	data tmp;
	h->obj[i] = x;
	while (j > 0) {
		if (h->obj[i].key > h->obj[j].key) {
			tmp = h->obj[j];
			h->obj[j] = h->obj[i];
			h->obj[i] = tmp;
			i = j;
			j >>= 1;
		} else break;
	}
}

data pop(max_heap* h)
{
	int i = 1, j = 2;
	data output = h->obj[1], tmp;
	h->obj[1] = h->obj[(h->size)--];
	while (j <= h->size) {
		if (j < h->size && h->obj[j^1].key > h->obj[j].key) j ^= 1;
		if (h->obj[j].key > h->obj[i].key) {
			tmp = h->obj[j];
			h->obj[j] = h->obj[i];
			h->obj[i] = tmp;
			i = j;
			j <<= 1;
		} else break;
	}
	return output;
}

const int inf = -1;
int leaf[200001];

typedef struct {
	int left, right, max;
} seg_node;

void init_node(seg_node v[], int k, int l, int r)
{
	v[k].left = l;
	v[k].right = r;
	v[k].max = inf;
	if (l < r) {
		init_node(v, k << 1, l, (l + r) / 2);
		init_node(v, (k << 1) ^ 1, (l + r) / 2 + 1, r);
	} else leaf[l] = k;
}

void update_node(seg_node v[], int k, int x)
{
	int i, j = leaf[k];
	v[j].max = x;
	for (i = j >> 1; i > 0; j = i, i >>= 1) v[i].max = (v[j].max > v[j^1].max)? v[j].max: v[j^1].max;
}

int get_max(seg_node v[], int k, int l, int r)
{
	int tmp[2];
	if (v[k].right < l || v[k].left > r) return inf;
	else if (v[k].left >= l && v[k].right <= r) return v[k].max;
	else {
		tmp[0] = get_max(v, k << 1, l, r);
		tmp[1] = get_max(v, (k << 1) ^ 1, l, r);
		return (tmp[0] < tmp[1])? tmp[1]: tmp[0];
	}
}

int BS_left(seg_node v[], int k, int l, int r, int x)
{
	int tmp;
	if (v[k].max < x || v[k].right < l || v[k].left > r) return r + 1;
	else if (v[k].left == v[k].right) return v[k].left;
	else {
		tmp = BS_left(v, k << 1, l, r, x);
		if (tmp <= r) return tmp;
		else return BS_left(v, (k << 1) ^ 1, l, r, x);
	}
}

int bin_packing(int N, int deg[], int F[])
{
	int u, Q;
	for (Q = 1; Q * Q < (N - 1) * 2; Q++);
	for (u = 1; u <= N; u++) chmax(&Q, deg[u]);
	if ((long long)(Q - 1) * (Q - 1) < (N - 1) * 2) {
		int i, j, k, u, q, max;
		static int dp[1001], num[1001], use[1001];
		for (i = 1; i <= Q; i++) num[i] = 0;
		for (u = 1; u <= N; u++) {
			F[u] = 0;
			num[deg[u]]++;
		}
		for (q = 1; q <= Q; q++) {
			for (i = 1; i <= Q; i++) if (num[i] > 0) break;
			if (i > Q) break;
			for (i = 1; i <= Q; i++) use[i] = 0;
			
			for (j = 1, dp[0] = 0; j <= Q; j++) dp[j] = -1;
			for (i = Q, max = 0; i >= 1 && max < Q; i--) {
				for (j = max; j >= 0; j--) {
					if (dp[j] < 0) continue;
					for (k = 1; k <= num[i] && j + i * k <= Q; k++) {
						if (dp[j+i*k] < 0) {
							dp[j+i*k] = i;
							chmax(&max, j + i * k);
						}
					}
				}
			}
			for (j = Q; dp[j] < 0; j--);
			while (j > 0) {
				use[dp[j]]++;
				j -= dp[j];
			}
			for (u = 1; u <= N; u++) {
				if (F[u] == 0 && use[deg[u]] > 0) {
					F[u] = q;
					use[deg[u]]--;
					num[deg[u]]--;
				}
			}
		}
		for (u = 1; u <= N; u++) if (F[u] == 0) break;
		if (u > N) return Q;
		
		Q++;
		for (i = 1; i <= Q; i++) num[i] = 0;
		for (u = 1; u <= N; u++) {
			F[u] = 0;
			num[deg[u]]++;
		}
		for (q = 1; q <= Q; q++) {
			for (i = 1; i <= Q; i++) if (num[i] > 0) break;
			if (i > Q) break;
			for (i = 1; i <= Q; i++) use[i] = 0;
			
			for (j = 1, dp[0] = 0; j <= Q; j++) dp[j] = -1;
			for (i = Q, max = 0; i >= 1 && max < Q; i--) {
				for (j = max; j >= 0; j--) {
					if (dp[j] < 0) continue;
					for (k = 1; k <= num[i] && j + i * k <= Q; k++) {
						if (dp[j+i*k] < 0) {
							dp[j+i*k] = i;
							chmax(&max, j + i * k);
						}
					}
				}
			}
			for (j = Q; dp[j] < 0; j--);
			while (j > 0) {
				use[dp[j]]++;
				j -= dp[j];
			}
			for (u = 1; u <= N; u++) {
				if (F[u] == 0 && use[deg[u]] > 0) {
					F[u] = q;
					use[deg[u]]--;
					num[deg[u]]--;
				}
			}
		}
		for (u = 1; u <= N; u++) if (F[u] == 0) exit(-1);
		return Q;
	}

	int i;
	static seg_node v[524288];
	init_node(v, 1, 1, Q);
	for (i = 1; i <= Q; i++) update_node(v, i, Q);

	static max_heap h;
	data d;
	h.size = 0;
	for (u = 1; u <= N; u++) {
		d.key = deg[u];
		d.id = u;
		push(&h, d);
	}
	while (h.size > 0) {
		d = pop(&h);
		u = d.id;
		i = BS_left(v, 1, 1, Q, deg[u]);
		F[u] = i;
		update_node(v, i, get_max(v, 1, i, i) - deg[u]);
	}
	return Q;
}

int solve(int N, int deg[], int *adj[], int F[], int *FF[])
{
	int Q = bin_packing(N, deg, F);
	
	int i, u;
	static int ed[200001][2][2];
	for (i = 1; i <= N - 1; i++) ed[i][0][0] = 0;
	for (u = 1; u <= N; u++) {
		for (i = 1; i <= deg[u]; i++) {
			if (ed[adj[u][i]][0][0] == 0) {
				ed[adj[u][i]][0][0] = u;
				ed[adj[u][i]][0][1] = i;
			} else {
				ed[adj[u][i]][1][0] = u;
				ed[adj[u][i]][1][1] = i;
			}
		}
	}
	
	int j, k;
	static int p[200001], *q[200001], *qq[200001], num[200001];
	for (i = 1; i <= Q; i++) num[i] = 0;
	for (u = 1; u <= N; u++) num[F[u]] += deg[u];
	for (i = 1; i <= Q; i++) {
		q[i] = (int*)malloc(sizeof(int) * (num[i] + 1));
		qq[i] = (int*)malloc(sizeof(int) * (num[i] + 1));
		num[i] = 0;
	}
	for (u = 1; u <= N; u++) {
		for (i = 1; i <= deg[u]; i++) {
			q[F[u]][++num[F[u]]] = u;
			qq[F[u]][num[F[u]]] = i;
		}
	}
	for (i = 1; i <= Q; i++) p[i] = i;
	shuffle_permutation(Q, p, Q * 10);
	for (i = 1; i <= Q; i++) {
		shuffle_permutation(Q, p, 100);
		for (j = 1, k = genrand() % Q + 1; j <= num[i]; j++, k++) {
			if (k > Q) k -= Q;
			FF[q[i][j]][qq[i][j]] = p[k];
		}
	}
	
	int w, r, ww, jj;
	for (k = 1; k <= N - 1; k++) {
		u = ed[k][0][0];
		i = ed[k][0][1];
		w = ed[k][1][0];
		j = ed[k][1][1];
		while (FF[u][i] == FF[w][j]) {
			// printf("[%d %d %d %d]\n", u, i, w, j);
			if (num[F[w]] == 1) {
				FF[w][j]++;
				if (FF[w][j] > Q) FF[w][j] -= Q;
			} else {
				do {
					r = genrand() % num[F[w]] + 1;
				} while (q[F[w]][r] == w && qq[F[w]][r] == j);
				ww = q[F[w]][r];
				jj = qq[F[w]][r];
				FF[w][j] ^= FF[ww][jj];
				FF[ww][jj] ^= FF[w][j];
				FF[w][j] ^= FF[ww][jj];
				u = ww;
				i = jj;
				w = ed[adj[u][i]][0][0] ^ ed[adj[u][i]][1][0] ^ u;
				j = ed[adj[u][i]][0][1] ^ ed[adj[u][i]][1][1] ^ i;
			}
		}
	}
	
	for (i = 1; i <= Q; i++) {
		free(q[i]);
		free(qq[i]);
	}
	return Q;
}

int main()
{
	int T, i, u, N, deg[200001], *adj[200001], F[200001], *FF[200001];
	scanf("%d", &T);
	while (T--) {
		scanf("%d", &N);
		for (u = 1; u <= N; u++) {
			scanf("%d", &(deg[u]));
			adj[u] = (int*)malloc(sizeof(int) * (deg[u] + 1));
			FF[u] = (int*)malloc(sizeof(int) * (deg[u] + 1));
			for (i = 1; i <= deg[u]; i++) {
				scanf("%d", &(adj[u][i]));
			}
		}
		printf("%d\n", solve(N, deg, adj, F, FF));
		for (u = 1; u <= N; u++) {
			printf("%d", F[u]);
			for (i = 1; i <= deg[u]; i++) printf(" %d", FF[u][i]);
			printf("\n");
		}
		for (u = 1; u <= N; u++) {
			free(adj[u]);
			free(FF[u]);
		}
	}
	
	/*
	scanf("%d", &N);
	while (1) {
		for (u = 1; u <= N; u++) deg[u] = 0;
		for (u = 2; u <= N; u++) {
			deg[u]++;
			deg[genrand() % (u - 1) + 1]++;
		}
		bin_packing(N, deg, F);
		printf("a");
	}
	*/
	fflush(stdout);
	return 0;
}
0