信息学奥赛一本通 香甜的黄油 题型:多源汇最短路

79 阅读1分钟

信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

视频题解:算法提高课图论第一节第三题

思想

很明显的多源汇最短路问题.但是本题不可以用floyd算法来做.因为floyd的时间复杂度是O(n3)O(n^{3}),本题n是800,800的3次方是2.56×1082.56×10^8,肯定会超时的.

spfa的复杂度是O(m)O(m),本题中的m是1450,n是800.总共的复杂度是1,160,000,不会超时.

所以本题可以用spfa来写.

code


#include<bits/stdc++.h>
using namespace std;
int n,p,m;
const int N=810,M=3000,INF=0x3f3f3f3f;
int id[N];
int h[N],e[M],w[M],ne[M],idx;
int dist[N];
bool st[N];
void add(int a,int b,int c)
{
	e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}

int spfa(int start)
{
	memset(dist,0x3f,sizeof dist);
	dist[start]=0;
	
	queue<int>q;
	q.push(start);
	st[start]=true;
	
	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(dist[j]>dist[t]+w[i])
    		{
    			dist[j]=dist[t]+w[i];
    			
    			if(!st[j])
    			{
    				q.push(j);
    				st[j]=true;
				}
			}
		}
	}
	
	//求每一头牛到起点的距离之和 
	int res=0;
	for(int i=0;i<n;i++)
	{
	
		int j=id[i];	//提取牛的编号 
		//如果某一头牛到起点的距离是INF,那么该牛到达不了该起点,需要重新枚举起点 
		if(dist[j]==INF) return INF;
		res+=dist[j];
	}
return res;
}
int main()
{
	cin>>n>>p>>m;
	for(int i=0;i<n;i++) cin>>id[i];
	
	memset(h,-1,sizeof h);
	for(int i=0;i<m;i++)
	{
		int a,b,c;cin>>a>>b>>c;
		add(a,b,c),add(b,a,c);
	}
	
	//枚举多个点作为起点,用spfa求一个最小值 
	int res=INF;
	for(int i=1;i<=p;i++) res=min(res,spfa(i));
	cout<<res<<endl;
	return 0;
}

image.png