codeforces1399E1 dfs+优先队列

1388E1 2000的题
题意:给你一个具有n个点,n-1条边的树,且每条边都有其权值,你可以对这些边进行操作,比如这条边的权值为w,进行操作之后变为w/2向下取整,问你最少进行多少次操作才能使得从根节点到各个叶子结点的权值之和小于S。
思路:对这棵树进行dfs一遍得到从根节点到叶子节点每条边要经过多少次,然后进行贪心,用优先对列来实现,因为他的操作是对w/2,进行向下取整所以不能说直接用经历的次数*该边的权值,会有精度损失。具体实现可看代码,memset是真的比for慢将近一倍

#pragma GCC optimize("Ofast","inline","-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pii;
#define rep(i, a, n) for(int i = a; i <= n; i++)
#define per(i, a, n) for(int i = n; i >= a; i--)
#define IOS std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define fopen freopen("file.in","r",stdin);freopen("file.out","w",stdout);
#define fclose fclose(stdin);fclose(stdout);
const int inf = 1e9;
const ll onf = 1e18;
const int maxn = 1e5+10;
#define int ll
inline int read(){
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
struct node
{
	int w, num;
	bool operator < (const node x)const{
		return (w-w/2)*num < (x.w-x.w/2)*x.num;	//注意这里优先队列的比较方式,是看w/2之后哪个损失更多
	}
};
std::vector<pii> g[maxn];
priority_queue<node> que;
ll res = 0;
int vis[maxn];
void dfs(int u, int pre){
	if(g[u].size()==1&&u!=1) vis[u]=1;
	for(auto to : g[u]){
		if(to.first==pre) continue;
		dfs(to.first, u);
		vis[u] += vis[to.first];
		res += vis[to.first]*to.second;
		que.push({to.second, vis[to.first]});
	}
}
inline void cf(){
	int t = read();
	while(t--){
		int n = read(), S = read();
		rep(i,1,n) g[i].clear();
		rep(i,1,n-1){
			int u=read(), v=read(), w=read();
			g[u].push_back({v,w}); g[v].push_back({u,w});
		}
		res = 0;
		rep(i,1,n) vis[i]=0;	//对vis进行初始化,for一遍是400多ms,memset是700多ms
		dfs(1,1);
		// printf("%lld ", res);
		int ans = 0;
		while(res>S){
			node tmp = que.top();que.pop();
			res -= tmp.num*(tmp.w-tmp.w/2);
			// printf("%lld ", res);
			tmp.w /= 2;
			que.push(tmp);
			ans++;
		}
		while(que.size()) que.pop();
		printf("%lld\n", ans);
	}
	return ;
}
signed main(){
	cf();
	return 0;
}

你可能感兴趣的:(codeforces,dfs,优先队列)