hihocoder 编程练习赛78 - D 泥泞的道路(最短路)

https://hihocoder.com/contest/offers78/problem/4

 

POINT:

从起点到某个点肯定有多条路,这些路可以抽象为(a,b),a代表经过的路径条数,b代表经过的路径总长度。

那么答案就= a*天数+b。

那么我们就要找到每个点的多对(a,b),当天数较多时,明显a小的有优势,而当天数较少时,可能a大的有优势。 

当然这些比较都是在a确定的情况下,b最小。这个可以用最短路处理出来。

然后每询问一个点,我们去遍历这个点的(a,b)对数,取最小的答案。

 

开dis[x][y],代表走了y条边到x这点的最短距离。

思路就是对于每一个y(每一个a),搜出最小的dis[x][y](最小的b)。

注意到y>=n的时候,就不要搜了,肯定再走重复的路了。

然后我们搜到了所有的dis[x][y],我们对于每一个x,不可能让y=1到y=n,全部都跑一遍。这样肯定是tle的。

维护一个前缀最小值,如果当前的dis[x][y]比这个最小值大,那么这个对就没有价值了。因为之前那个最小值应对的a肯定比这个A小。而b也比这个B=dis[x][y]小。而Ax+B>ax+b一定成立,所以没有价值。(这个对应main函数里的Q次询问之前的预处理操作,主要在qq这个vector里体现)

堆优化重载运算符<是反着的!!,总是忘记,大家当作没看到。

 

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define LL long long
const int N = 1111+55;
const int inf = 0x3f3f3f3f;
vectorG[N];
vectorW[N];
struct node
{
	int a,b,c;
	node(int aa,int bb,int cc)
	{
		a=aa;b=bb;c=cc;
	}
	bool friend operator < (node a,node b)
	{
		return a.a>b.a;
	}
};
int n,m,Q;

int dis[N][N],vis[N][N];
void dij()
{
	memset(dis,inf,sizeof dis);memset(vis,0,sizeof vis);
	dis[1][0]=0;
	priority_queueq;
	q.push(node(0,1,0));
	while(!q.empty()){
		node x = q.top();
		q.pop();
		int u=x.b,p=x.c;
		if(vis[u][p]||p>n) continue;
		vis[u][p]=1;
		for(int i=0;i=dis[u][p]+w){
				dis[v][p+1]=dis[u][p]+w;
				q.push(node(dis[v][p+1],v,p+1));
			}
		}
	}

}

vector qq[N];

int main()
{
	scanf("%d%d%d",&n,&m,&Q);
	for(int i=1;i<=m;i++){
		int x,y,w;
		scanf("%d%d%d",&x,&y,&w);
		G[x].push_back(y);G[y].push_back(x);
		W[x].push_back(w);W[y].push_back(w);
	}
	dij();
	for(int i=2;i<=n;i++){
		int Min=inf;
		for(int j=1;j<=n;j++){
			if(dis[i][j]>=Min) ;
			else{
				Min=dis[i][j];
				qq[i].push_back(node(j,dis[i][j],0));
			}
		}
	}
	while(Q--){
		int i,j;scanf("%d%d",&j,&i);
		if(j==1) printf("0\n");
		else{
			LL ans=0x3f3f3f3f3f3f3f3f;
			for(int k=0;k

 

你可能感兴趣的:(其他,最短路)