洛谷P1261服务器储存信息问题

Posted Ja_King_ZH

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P1261服务器储存信息问题相关的知识,希望对你有一定的参考价值。

原题链接:https://www.luogu.com.cn/problem/P1261?contestId=60077

题意:

找到各个服务器感兴趣的服务器的总和。a对b感兴趣的条件为:不存在rank比b大且到a的距离比b小。

题解:

读完题,很明显,直接对每个点跑一遍spfa或者dijkstra,在用一个ans记录答案即可。但是会tle…
所以需要优化,根据rank进行优化是比较好的,因为rank数据小且与答案挂钩。rank的优化比较难想,具体证明如下:
首先,需要一个数组:d[i][j],此数组表示rank大于等于i的所有点到j点的最短距离,优化后的d我们可以直接拿来用,相当于 dist[j] < d[ra[s] + 1][j] 时,才能加入队列中,大量的降低了时间复杂度。
此等式怎么来的呢?
dist[j] = dist[t] + w[i]
首先,如上式,j点可以由t点更新时满足:dist[j] < d[ra[s] + 1][j](即当前j点到起点s的距离比所有rank大于s的最短距离小,证明该点为起点s感兴趣服务器)
所以,我们需要做两次spfa,第一次找到所有rank大于等于i的所有点到j点的最短距离,即求出d[i][j]。
第二次spfa便利用第一次求得的d[i][j]进行ans的记录。
ac代码如下:

#include<iostream>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<queue>
#include<deque>
#include<map>
#include<cstring>
#include<vector>
using namespace std;

const int N = 3e4 + 10, M = 3e5 + 10;
int ra[N];
int e[M], ne[M], w[M], h[N], idx;
int n, m;
int d[15][N], dist[N];
int ans;
bool st[N],nst[N];

void add(int a, int b, int c)

	e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;


void spfa1(int x)

	for (int i = 0; i <= n; i++) d[x][i] = 1e9;
	memset(st, 0, sizeof st);
	queue<int>q;
	for (int i = 1; i <= n; i++)
	
		if (ra[i] == x)
		
			d[x][i] = 0;
			q.push(i);
		
	
	while (!q.empty())
	
		int t = q.front();
		q.pop();
		st[t] = false;
		for (int i = h[t]; i != -1; i = ne[i])
		
			int j = e[i];
			if (d[x][j] > d[x][t] + w[i])
			
				d[x][j] = d[x][t] + w[i];
				if (!st[j])
				
					q.push(j);
					st[j] = true;
				
			
		
	


void spfa2(int s)

	memset(dist, 0x3f, sizeof dist);
	memset(st, 0, sizeof st);
	memset(nst, 0, sizeof nst);
	queue<int>q;
	q.push(s);
	dist[s] = 0;
	while (!q.empty())
	
		int t = q.front();
		q.pop();
		st[t] = false;
		if (!nst[t])
		
			ans++;
			nst[t] = true;
		
		for (int i = h[t]; i != -1; i = ne[i])
		
			int j = e[i];
			if (dist[j] > dist[t] + w[i])
			
				dist[j] = dist[t] + w[i];
				if (!st[j] && dist[j] < d[ra[s] + 1][j])
				
					st[j] = true;
					q.push(j);
				
			
		
	


int main()

	cin >> n >> m;
	memset(h, -1, sizeof h);
	for (int i = 1; i <= n; i++)cin >> ra[i];
	for (int i = 0; i < m; i++)
	
		int a, b, c;
		cin >> a >> b >> c;
		add(a, b, c), add(b, a, c);
	
	for (int i = 1; i <= 10; i++) spfa1(i);
	for (int i = 9; i >= 1; i--)
	
		for (int j = 1; j <= n; j++)
		
			d[i][j] = min(d[i][j], d[i + 1][j]);
		
	
	for (int i = 1; i <= n; i++)spfa2(i);
	cout << ans << endl;
	return 0;

以上是关于洛谷P1261服务器储存信息问题的主要内容,如果未能解决你的问题,请参考以下文章

Gym-101242B:Branch Assignment(最短路,四边形不等式优化DP)

洛谷 [p2294] [HNOI2005] 狡猾的商人

洛谷P2661 信息传递 类似tarjan 强连通 灌水

洛谷 P4342 / poj 1179 Polygon

BZOj 墨墨的等式(转化为最短路)题解

bzoj2118 墨墨的等式