题解 CF1244D 【Paint the Tree】

SIGSEGV

2019-10-14 19:17:06

Solution

观察可得如果能够成功染色,那么**任何一个点的度数都不能超过3** 那么,这个树就是一条链...... ```cpp #include <bits/stdc++.h> using namespace std; const int N = 100005; int n,c[4][N],deg[N]; vector<int> e[N]; long long val[4][4]; int out[N]; long long dfs(int pos,int fa,int l1,int l2) //第一遍搜答案 { for (int i = 1;i <= 3;i++) if (i != l1 && i != l2) { if (e[pos].size() == 1) return c[i][pos]; int nxt = e[pos][0]; if (nxt == fa) nxt = e[pos][1]; return c[i][pos] + dfs(nxt,pos,i,l1); } throw; } void print(int pos,int fa,int l1,int l2) //第二遍"打印"答案 { for (int i = 1;i <= 3;i++) if (i != l1 && i != l2) { out[pos] = i; if (e[pos].size() == 1) return; int nxt = e[pos][0]; if (nxt == fa) nxt = e[pos][1]; return print(nxt,pos,i,l1); } } int main () { ios::sync_with_stdio(false); cin >> n; for (int i = 1;i <= 3;i++) for (int j = 1;j <= n;j++) cin >> c[i][j]; int t1,t2; for (int i = 1;i < n;i++) { cin >> t1 >> t2;++deg[t1];++deg[t2]; e[t1].push_back(t2);e[t2].push_back(t1); } int pos = 0,cnt = 0; for (int i = 1;i <= n;i++) if (deg[i] == 1) ++cnt,pos = i; else if (deg[i] > 2) {cout << -1 << endl;return 0;} if (cnt != 2) {cout << -1 << endl;return 0;} int nxt = e[pos][0],nn = nxt; if (e[nxt][0] == pos) nxt = e[nxt][1];else nxt = e[nxt][0];//获取链上的前2个点 long long ans = LLONG_MAX; for (int i = 1;i <= 3;i++) for (int j = 1;j <= 3;j++) if (i != j) ans = min(ans, val[i][j] = dfs(nxt,nn,i,j) + c[j][pos] + c[i][nn]);//枚举前2个染什么,后面的都是确定的 for (int i = 1;i <= 3 && !out[1];i++) for (int j = 1;j <= 3;j++) if (i != j && ans == val[i][j]) { cout << ans << endl; out[pos] = j;out[nn] = i; print(nxt,nn,i,j); break; } for (int i = 1;i <= n;i++) cout << out[i] << ' '; return 0; } ```