CodeForces - 1141G Privatization of Roads in Treeland(二分,DFS)

题目链接

https://codeforces.com/contest/1141/problem/G

题目大意:

n n n个城市, n − 1 n-1 n1条路,要求用最少的公司修路,同时使得不满足条件的城市数量小于等于 k k k。当一个城市的路有两个以上相同的公司来修时,这个城市不满足题目条件。

思路:

首先统计每个节点的度,如果一个节点的度等于 m m m,那么这个城市一定可以由 m m m个不同的公司来修,这个城市一定符合条件。所以所有节点中最大的度,即使所需要最多的公司数。
由于公司越多,不满足条件的城市越少,用二分找出最少且满足条件的公司。
最后利用DFS对树进行染色,保证当前节点与父亲节点之间,以及当前节点的孩子之间所连的边不同颜色。

#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
using namespace std;
int n,k;
int dg[200010];
vector<pair<int,int>> ed[200010];
int comp=0,C[200010];
int mxd=0;
int judge(int mid){
	int num=0;
	for(int i=1;i<=n;i++){
		if(dg[i]>mid){
			num++;
			if(num>k) return 0;
		}
	}
	return 1;
}
void dfs(int u,int fa,int col){//当前节点,父亲节点,当前节点与父亲节点的边的颜色(上一条边的颜色)
	int color=0;
	for(auto to:ed[u]){
		int nxt=to.first,ind=to.second;
		if(nxt!=fa){
			if(color==col){//确保与父亲节点之间的边颜色不相同
				color=(color+1)%comp;
			}
			C[ind]=color;
			dfs(nxt,u,color);
			
			color=(color+1)%comp;//与孩子节点之间的边颜色不相同
		}
	}
}
int main(){
	cin>>n>>k;
	for(int i=1;i<=n-1;i++){
		int x,y;
		cin>>x>>y;
		dg[x]++;
		dg[y]++;
		mxd=max(mxd,max(dg[x],dg[y]));//统计最大的度
		
		ed[x].pb(mp(y,i));
		ed[y].pb(mp(x,i));
	}
	
	int l=1,r=mxd;
	while(l<r){//二分查找最小的公司
		int mid=(l+r)>>1;
		if(judge(mid)) r=mid;
		else l=mid+1;
	}
	comp=l;
	
	dfs(1,-1,-1);
	cout<<comp<<"\n";
	for(int i=1;i<=n-1;i++) cout<<C[i]+1<<" ";
	cout<<"\n";
	return 0;
} 

posted @ 2019-03-24 10:14  xzhws  阅读(36)  评论(0编辑  收藏  举报