luogu P1828 【香甜的黄油 Sweet Butter】

9012年了,spfa已经noip了,我们还是用dijkstra+堆优化吧!

做法:在一开始时统计每个牧场牛的个数,枚举放黄油的牧场,然后做p遍dijkstra,最后统计每个点的贡献,即为:该点到枚举点的最短路\(\times\)该点有牛的个数,最后取每个枚举点的最小值,就做完了。dijktra每次\(O(p\log p)\),还有枚举点的\(O(p)\),所以总时间复杂度\(O(p^2\log p)\)

dijkstra的模板可以去
P4779 看,这里就不再多说

\(Code:\)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
inline int read(){//快读
	register int x=0,v=1,ch=getchar();
	while(!isdigit(ch)){if(ch=='-')v=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^'0');ch=getchar();}
	return x*v;
}
const int MAX=1455,N=805;
struct E{//链式前向星存图
	int e,next,w;
}e[MAX<<1];
int head[N],cnt=1; 
inline void add(int u,int v,int w){
	e[cnt]=(E){v,head[u],w};
	head[u]=cnt++;
}
int n,c,p,s[N];
struct Node{
	int dis,pos;
	bool operator < (const Node&x)const{
		return x.dis<dis;
	}
};
int d[N],vis[N];
priority_queue<Node>q;
inline void dijkstra(int s){//dijkstra
	memset(d,0x3f3f3f3f,sizeof(d));
	memset(vis,0,sizeof(vis));
	d[s]=0;
	q.push((Node){0,s});
	while(!q.empty()){
		Node tmp=q.top();
		int x=tmp.pos;
		q.pop();
		if(vis[x])continue;
		vis[x]=1;
		for(register int i=head[x];i;i=e[i].next){
			int y=e[i].e;
			if(d[y]>d[x]+e[i].w){
				d[y]=d[x]+e[i].w;
				if(!vis[y])q.push((Node){d[y],y});
			}
		}
	}
}
int u,v,w,Sum,Ans=0x3f3f3f3f;
int main(){
	n=read();p=read();c=read();
	for(register int i=1;i<=n;++i){
		++s[read()];//即为统计每个牧场拥有的牛的个数
	} 
	for(register int i=1;i<=c;++i){
		u=read(),v=read(),w=read();
		add(u,v,w);add(v,u,w);
	}
	for(register int i=1;i<=p;++i){//枚举
		dijkstra(i);
		Sum=0;
		for(register int j=1;j<=p;++j){
			Sum+=s[j]*d[j];//每个点对答案的贡献
		}
		Ans=Ans<Sum?Ans:Sum;//取最小值
	}
	printf("%d\n",Ans);//输出答案
	return 0;
}

posted @ 2019-12-22 22:30  Lates  阅读(190)  评论(0)    收藏  举报