2019CCPC网络赛1004path(图bfs+优先级队列)

path

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2120    Accepted Submission(s): 486

 

Problem Description

You have a directed weighted graph with n vertexes and m edges. The value of a path is the sum of the weight of the edges you passed. Note that you can pass any edge any times and every time you pass it you will gain the weight.

Now there are q queries that you need to answer. Each of the queries is about the k-th minimum value of all the paths.

Input

The input consists of multiple test cases, starting with an integer t (1≤t≤100), denoting the number of the test cases.
The first line of each test case contains three positive integers n,m,q. (1≤n,m,q≤5∗104)

Each of the next m lines contains three integers ui,vi,wi, indicating that the i−th edge is from ui to vi and weighted wi.(1≤ui,vi≤n,1≤wi≤109)

Each of the next q lines contains one integer k as mentioned above.(1≤k≤5∗104)

It's guaranteed that Σn ,Σm, Σq,Σmax(k)≤2.5∗105 and max(k) won't exceed the number of paths in the graph.

Output

For each query, print one integer indicates the answer in line.

Sample Input

1

2 2 2  (点数、边数、q次询问)

1 2 1  (点1连接点2,权值为1)

2 1 2

3

4

Sample Output

3 3

Hint

1->2 value :1

2->1 value: 2

1-> 2-> 1 value: 3

2-> 1-> 2 value: 3

链接:http://acm.hdu.edu.cn/showproblem.php?pid=6705

题意:求第k短的路线。

题解:先开始想的时候,可能认为Dijstra或者并查集思路,但是都感觉思路不太对,比赛结束后群里讨论说是bfs+优先级队列,确实不敢想象这是正解,然后去试着做,将新遇到的边加入优先级队列中,优先级队列顶端是最小值,每次出队就记载下来当前为第几次出队,则为第几最小值,结果提交71000K内存超限,内存优化不成,很明显是优先级队列存炸了,所以当前做法肯定有问题!接着去分析怎样才能让优先级队列存的量减少,其实优先级队列最有效的值,就是顶端要出队的值,其他的值如果没有机会出队,那就没有必要进优先级队列,所以当前点要走向下一点时,没必要枚举每个“下一点”,只需要选择最小的边所连接的下一点入队,其他的边先不加到优先级队列内,在该点要出队的时候,说明当前为最小值,就该找到当初枚举时候第二小边入队,然后第三小、第四小...一直重复此过程,就这样在优先级队列内跑结果。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
struct node
{
	int to;//当前点 
	long long v;//当前累计值 
	int from;//从哪个点来 
	int num;//从哪个点来的第几个点 
	friend bool operator <(node a,node b){
        return a.v>b.v;//小的优先级高
    }
};
priority_queue<node>s;
vector<node>maps[50005];
int arr[50005];
int n,m,q,maxk;
bool cmp(node x,node y)
{
	return x.v<y.v;
}
void solve()
{
	long long opt[50005]={0};
	while(!s.empty()) s.pop();
	for(int i=1;i<=n;i++)
	{
		if(!maps[i].empty())
		s.push((node){maps[i][0].to,maps[i][0].v,i,1});
	}
	for(int len=1;len<=maxk;len++)
	{
		node top=s.top();
		opt[len]=top.v;
		s.pop();
		if(maps[top.to].size())
		s.push((node){maps[top.to][0].to,maps[top.to][0].v+top.v,top.to,1});
		if(maps[top.from].size()>top.num)
		s.push((node){maps[top.from][top.num].to,top.v-maps[top.from][top.num-1].v+maps[top.from][top.num].v,top.from,top.num+1});
	}
	for(int i=1;i<=q;i++)
		printf("%lld\n",opt[arr[i]]);
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		for(int i=0;i<=n;i++)
		{
			maps[i].clear();
			arr[i]=0;
		}
		scanf("%d%d%d",&n,&m,&q);
		int a,b;
		long long c;
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d%lld",&a,&b,&c);
			maps[a].push_back((node){b,c});
		}
		maxk=0;
		for(int i=1;i<=q;i++)
		{
			scanf("%d",&arr[i]);
			maxk=max(maxk,arr[i]);
		}
		for(int i=1;i<=n;i++)
		sort(maps[i].begin(),maps[i].end(),cmp);
		solve();
	}
	return 0;
}
/*
测试数据
5 7 15
1 2 10
1 3 3
1 4 6
1 5 2
5 2 3
4 2 3
2 1 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
*/
发布了39 篇原创文章 · 获赞 27 · 访问量 4133

猜你喜欢

转载自blog.csdn.net/qq_43381887/article/details/100116873