点权(bfs,最短路,牛客练习赛93)

Linking


题意:

简化后的题意为:
给出节点数为 n n n 的一棵树,每条边有边权 c i c_i ci ( n ≤ 1 0 5 , c i ≤ 1 0 3 ) (n \le 10^5 ,c_i \le 10^3) (n105,ci103)
一个点必须由两个相邻的已更新的点更新,花费为两条边的边权之和。
初始入度小于2的节点(叶子节点)已更新。
对于每个点,求出能够将其更新的最小花费。如不可更新,输出-1。

思路:

从所有的叶子节点往中间更新,两个已更新的节点才能更新一个节点。求得到每个节点所需要的最小花费。
乍一看,是多源bfs,由所有的叶子节点往中间搜。
但是需要注意的是,两个节点才能更新一个节点。就是要选花费最少的两个相邻节点来更新当前节点。

  • 于是就需要每个点都开一个小根堆,按照 点权+边权 将所有相邻已更新的点都存到小根堆中。
  • 如果一个点的小根堆中至少有两个点了,说明这个点可以被更新了。于是就取花费最小的两个邻点(队首两元素)花费之和,放入最短路的优先队列中。
  • 每次取优先队列队首元素,去更新与其相邻的点。

注意:如果优先队列的队首元素该出队了,那么能够更新这个点的所有相邻节点都一定在其小根堆中,并且队首元素这个的花费是最少的。
(这里参照dijkstra求最短路原理,只有一个点所有相邻已更新的节点都对其判断过之后,将其更新为最短距离,这个节点才会从优先队列中出队,去更新其他节点。也就是说,如果一个点出队了,那么这个点一定被更新为最短距离了。
而该点出队后,优先队列中可能还存有之前其他相邻点更新的非最短距离,如果这个非最短距离出队了,却发现这个点之前已经出队过了,已经更新过最短距离了,那么这个非最短距离就会跳过。这也就是为什么每个节点出队后,要将其 f 数组设为 true 的原因。)

Code:

const int N = 200010, mod = 1e9+7;
int T, n, m;
int a[N];
int e[N], ne[N], h[N], idx, w[N];
int ru[N], v[N], cost[N];
int f[N];

void add(int x,int y,int z){
    
    
	e[idx]=y,w[idx]=z,ne[idx]=h[x],h[x]=idx++;
}

priority_queue<int, vector<int>, greater<int> > q[N];

void bfs()
{
    
    
	priority_queue<PII,vector<PII>,greater<PII> > que;
	
	for(int i=1;i<=n;i++)  //所有叶子节点入队
		if(ru[i]<2) que.push({
    
    0,i});
	
	while(que.size())
	{
    
    
		int x=que.top().se, y=que.top().fi;
		que.pop();
		if(f[x]) continue;
		f[x]=1;
		
		cost[x] = y;
		
		for(int i=h[x];i!=-1;i=ne[i])
		{
    
    
			int tx=e[i];
			
			q[tx].push(cost[x]+w[i]);
			
			if(q[tx].size()>1){
    
    		//取该点的小根堆的前两元素,放入优先队列
				int x=q[tx].top();
				q[tx].pop();
				que.push({
    
    x+q[tx].top(),tx});
				q[tx].push(x);
			}
		}
	}
}

signed main(){
    
    
	cin>>n;
	
	mem(h,-1);
	for(int i=1;i<n;i++)
	{
    
    
		int x,y,z;cin>>x>>y>>z;
		add(x,y,z);
		add(y,x,z);
		ru[x]++,ru[y]++;
	}
	
	bfs();
	
	for(int i=1;i<=n;i++)
		if(ru[i]<2) cout<<0<<" ";
		else if(q[i].size()>1) cout<<cost[i]<<" ";
		else cout<<-1<<" ";
	
	return 0;
}

用到了bfs的思想,dijkstra的实现,加上有点思维的每个点开一个小根堆。
算是综合的一道图论题了。不错!

猜你喜欢

转载自blog.csdn.net/Mr_dimple/article/details/121877464
今日推荐