【 Codeforces Round #547 (Div. 3) G】Privatization of Roads in Treeland【树上贪心问题】

题意:

现在要对一颗树上的边进行染色。如果一个节点连接的边中有大于等于两条颜色相同,则这个节点为不好的点。现在最多只能有 k k k 个不好的点,问最多需要几种颜色可以将树上所有的边进行染色。


思路:

比赛的时候前面几题写太慢了,导致没有写到这一题,还是太弱…哭。

我们来考虑这道题如何解决。首先既然有 k k k 个不好的点,一个直接的想法就是让前 k k k 个度数最大的点成为不好的点,然后我们可以发现对于第 k + 1 k+1 k+1 个节点来说,这个节点的度数就是本题所需要的颜色数。

贪心地证明一下,因为最后的颜色数一定等于没被污染的点中度数最大的点的度数,所以我们选择让前 k k k 个点成为不好的点是最优的。然后就是染色了,对于不好的点,所有边染成一个颜色。其余的点,即染成父节点未染过的颜色即可,跑一遍 d f s dfs dfs,循环染色即可。


代码:

#include 
#include 
#include 
#include 
#include 
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define LOG1(x1,x2) cout << x1 << ": " << x2 << endl;
#define LOG2(x1,x2,y1,y2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << endl;
typedef long long ll;
typedef double db;
const db EPS = 1e-9;
using namespace std;
const int N = 2*1e5+1000;

int n,k,tot,head[N],cnt,d[N],vis[N],book[N];	//cnt —— color 数目
struct Edge{
	int to,next,color;
}e[2*N];
struct Node{
	int id,v;
	bool operator < (Node tmp) const {
		return v > tmp.v;
	}
}t[N];
map<pair<int,int>,int> mp; //mp[make_pair(Node,color)] = 边数

void add(int x, int y){
	e[++tot].to = y, e[tot].next = head[x], head[x] = tot, e[tot].color = 0;
	e[tot+n-1].to = x, e[tot+n-1].next = head[y], head[y] = tot+n-1, e[tot+n-1].color = 0;
}

int find(int x, int y, int i){
	while(1){
		if(vis[x]){
			if(vis[y]) return i;
			else{
				if(mp.find(make_pair(y,i)) == mp.end()) return i;	
			}
		}
		else{
			if(vis[y]){
				if(mp.find(make_pair(x,i)) == mp.end()) return i;	
			}
			else{
				if(mp.find(make_pair(x,i)) == mp.end() && mp.find(make_pair(y,i)) == mp.end()) return i;
			}
		}
		i = (i+1)%cnt;
		if(!i) i = cnt;
	}
}

void dfs(int x, int hp){
	for(int i = head[x]; i; i = e[i].next){
		if(e[i].color) continue;
		int y = e[i].to;
		e[i].color = find(x,y,hp);
		hp = (hp+1)%cnt;
		if(hp == 0) hp = cnt;
		if(i >= n) e[i-n+1].color = e[i].color;
		else e[i+n-1].color = e[i].color;
		mp[make_pair(x,e[i].color)] = 1;
		mp[make_pair(e[i].to,e[i].color)] = 1;
		if(!book[y]) book[y] = 1, dfs(y,hp);
	}
}

int main()
{
	mp.clear();
	scanf("%d%d",&n,&k);
	rep(i,1,n) t[i].id = i;
	rep(i,1,n-1){
		int x,y; scanf("%d%d",&x,&y);
		add(x,y);
		t[x].v++, t[y].v++;
	}
	sort(t+1,t+1+n);
	rep(i,1,k) vis[t[i].id] = 1;
	// rep(i,1,n)
		// solve(t[i].id);
	cnt = t[k+1].v;
	book[t[1].id] = 1;
	dfs(t[1].id,1);
	printf("%d\n",cnt);
	rep(i,1,n-1){
		printf("%d",e[i].color);
		if(i == n-1) printf("\n");
		else printf(" ");
	}
	return 0;
}

你可能感兴趣的:(#,思维题,基础算法及操作)