香甜的黄油(SPFA)

女生的网名这么多〃 提交于 2020-01-16 03:34:41

香甜的黄油(SPFA)

Description

农夫John发现做出全威斯康辛州最甜的黄油的方法:糖。把糖放在一片牧场上,他知道N(1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油。当然,他将付出额外的费用在奶牛上。
  农夫John很狡猾。像以前的Pavlov,他知道他可以训练这些奶牛,让它们在听到铃声时去一个特定的牧场。他打算将糖放在那里然后下午发出铃声,以至他可以在晚上挤奶。
  农夫John知道每只奶牛都在各自喜欢的牧场(一个牧场不一定只有一头牛)。给出各头牛在的牧场和牧场间的路线,找出使所有牛到达的路程和最短的牧场(他将把糖放在那)

Input

第一行: 三个数:奶牛数N,牧场数(2<=P<=800),牧场间道路数C(1<=C<=1450)
第二行到第N+1行: 1到N头奶牛所在的牧场号
第N+2行到第N+C+1行: 每行有三个数:相连的牧场A、B,两牧场间距离D(1<=D<=255),当然,连接是双向的

==Output ==

一行 输出奶牛必须行走的最小的距离和

Sample Input

3 4 5
2
3
4
1 2 1
1 3 5
2 3 7
2 4 3
3 4 5

样例图形

         P2  
P1 @--1--@ C1
    \    |\
     \   | \
      5  7  3
       \ |   \
        \|    \ C3
      C2 @--5--@
         P3    P4

Sample Output

8 

{说明:放在4号牧场最优 }

SPFASPFA
前世:福特算法
算法描述:SPFA是Bellman-Ford(福特)算法的一种队列实现,减少了不必要的冗余计算。
算法思想:
SPFA算法与广搜类似,但是唯一不同的是广搜一旦弹出队列,就不能再进入队列,而SPFA能重复进入队列!!
算法实现:

	dis[i]记录从起点s到i的最短路径,w[i][j]记录连接i,j的边的长度。pre[v]记录前趋。
    team[1..n]为队列,头指针head,尾指针tail。
    布尔数组exist[1..n]记录一个点是否现在存在在队列中。
    初始化:dis[s]=0,dis[v]=∞(v≠s),memset(exist,false,sizeof(exist));
    起点入队team[1]=s; head=0; tail=1;exist[s]=true;
    do
    { 
    1、头指针向下移一位,取出指向的点u。
    2、exist[u]=false;已被取出了队列
    3for与u相连的所有点v          //注意不要去枚举所有点,用数组模拟邻接表存储
              if (dis[v]>dis[u]+w[u][v])
                 {
                      dis[v]=dis[u]+w[u][v];
                      pre[v]=u;
                     if (!exist[v]) //队列中不存在v点,v入队。
                       {
                                    //尾指针下移一位,v入队;
                                  exist[v]=true;
                       }}
    while (head < tail);

-------------------------------------------------------------------------------------------------------华丽的分割线!

code:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int b[5010],t=0,head[5010],dis[5010][5010],f[5010],z[5010];
struct node
{
	int x,y,next,zz;
}a[5010];
void add(int xx,int yy,int sum)  //领接表,大家都懂!
{
	a[++t].x=xx;
	a[t].y=yy;
	a[t].next=head[xx];
	a[t].zz=sum;
	head[xx]=t;
}
void spfa(int x)  //SPFA模板
{
	memset(z,127/3,sizeof(z));
	dis[x][x]=1;
	int h=0,t=1;
	f[1]=x;
	z[x]=0;
	do
	{
		h++; 
		int tx=f[h];
		for(int i=head[tx];i;i=a[i].next)
		{
			if(z[a[i].y]>z[tx]+a[i].zz)
			{
				z[a[i].y]=z[tx]+a[i].zz;
				if(dis[x][a[i].y]==0){
					t++;
					dis[x][tx]=1;
					f[t]=a[i].y;
				}
			}
		}
		dis[x][tx]=0;
	}while(h<=t); 
}
int main()
{
	int n,p,c,a,bb,d;
	cin>>n>>p>>c;
	for(int i=1;i<=n;i++) cin>>b[i];
	for(int i=1;i<=c;i++)
	{
		cin>>a>>bb>>d;
		add(a,bb,d);
		add(bb,a,d);
	}
	int minn=2147483647;
	for(int i=1;i<=p;i++) 
	{
		spfa(i);
		int anss=0;
		for(int j=1;j<=n;j++) anss=anss+z[b[j]];
		minn=min(minn,anss);
	}
	cout<<minn<<endl;
	return 0;
}

code(STL):

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int d[100010],n,m,q,dis[1000][1000],hd[100000],tot;
struct node{
	int x,y,next,w;
}a[100001];
int v[100010];
int p[10010];
void add(int x,int y,int z){
	tot++;
	a[tot].x=x;
	a[tot].y=y;
	a[tot].w=z;
	a[tot].next=hd[x];
	hd[x]=tot;
}
void spfa(int x){
	memset(v,0,sizeof(v));
	dis[x][x]=0;
	v[x]=1;
	queue<int>p;
	p.push(x);
	while(!p.empty()){
		int x1=p.front();p.pop();
		for(int j=hd[x1];j;j=a[j].next){
			if(dis[x][a[j].y]>dis[x][x1]+a[j].w){
				dis[x][a[j].y]=dis[x][x1]+a[j].w;
				if(v[a[j].y]==0){
					v[x1]=1;
					p.push(a[j].y);
				}
			}
		}
		v[x1]=0;
	} 
}
int main(){
	memset(dis,100,sizeof(dis));
	cin>>q>>n>>m;
	for(int i=1;i<=q;i++){
		cin>>d[i];
	}
	for(int i=1;i<=m;i++){
		int x,y,z;
		cin>>x>>y>>z;
		add(x,y,z);
		add(y,x,z);
	}
	for(int i=1;i<=n;i++){
		spfa(i);
	}
	int minn=1000000000,k;
	for(int i=1;i<=n;i++){
		int anss=0;
		for(int j=1;j<=q;j++){
			anss+=dis[d[j]][i];
		}
		minn=min(minn,anss);
	}
	cout<<minn<<endl;
	return 0;
}


谢谢

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!