CodeForces 805E Ice cream coloring dfs染色
题意:给出一棵树 T,每个点有一个集合,集合中的数代表冰淇淋的类型。现在冰淇淋的类型 1~m 要构成一个新图 G, T 上的每个点集里的数都互相连边。且 T 中只有相邻的点才会有相同的类型。 要你给图 G 中的点染色,相邻的点不能染相同颜色,问至少要多少种颜色。
tags: 吐槽一句,题目意思不说清楚,故意卡人。。
有两点:
1】Vertices which have the i-th (1 ≤ i ≤ m) type of ice cream form a connected subgraph. 这就是说有相同类型的点会构成连通子图,也就是说只有相邻的点才会有相同的类型。故可以直接 dfs,不会有矛盾。
2】Please note that we consider that empty set of vertices form a connected subgraph in this problem. 会有点是空集,这就要特判一下。不然会 WA129 (不要问我为什么知道)
其实只要通过 T 直接dfs即可,当前到 u 点时,看 u 中哪些类型没有染过,就染上没有用过的颜色即可。
但是,不知道为什么, u 里染过色的要排序之后再去找没染过的,不然总是超时。。不太明白为什么这样就不超时了。
// 805E #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 300005; int n, m, col[N], need[N]; vector<int > s[N], G[N]; /* bool used[N]; void dfs(int u, int fa) { mes(used, false); int cnt1=0; for(auto ai : s[u]) if(col[ai]) { used[col[ai]]=true; ++cnt1; } int cnt=0; rep(i,1,m) { if(cnt==s[u].size()-cnt1) break; if(!used[i]) need[++cnt]=i; } int now=0; for(auto ai : s[u]) if(col[ai]==0) { col[ai]=need[++now]; } for(auto to : G[u]) if(to!=fa) dfs(to, u); }*/ set<int > used; void dfs(int u, int fa) { used.clear(); for(auto ai : s[u]) if(col[ai]) used.insert(col[ai]); int now=1; for(auto ai : s[u]) if(col[ai]==0) { while(used.find(now)!=used.end()) ++now; col[ai]=now; ++now; } for(auto to : G[u]) if(to!=fa) dfs(to, u); } int main() { scanf("%d%d", &n, &m); int si, ai, ans=0; rep(i,1,n) { scanf("%d", &si); ans = max(ans, si); rep(j,1,si) { scanf("%d", &ai); s[i].PB(ai); } } int u, v; rep(i,1,n-1) { scanf("%d%d", &u, &v); G[u].PB(v); G[v].PB(u); } dfs(1, 0); ans = max(ans, 1); printf("%d\n", ans); rep(i,1,m) if(col[i]) printf("%d ", col[i]); else printf("1 "); puts(""); return 0; }