Logu P1828 Sweet Butter (Graph Theory-Floyd/SPFA)

Source: Luogu P1828, JZOJ #316

Title Description

Farmer John found a way to make the sweetest butter in Wisconsin: sugar.Put the sugar on a pasture and he knows that N (1<=N<=500) cows will come to lick it, so he can make super sweet butter for a good price.Of course, he will pay extra for the cows.

Farmer John is cunning.Like Pavlov before, he knew he could train the cows to go to a specific ranch when they heard the bell.

He planned to put the sugar there and ring in the afternoon so that he could milk in the evening.Farmer John knows that each cow has its own favorite pasture (a pasture may not have only one cow).

Give the routes of the cattle between the pasture and the pasture, find the route and the shortest pasture for all the cattle (he will put the sugar there)

Solving problems

  • This graph topic can be solved by two shortest-path algorithms: FloydFloydFloyd and SPF SPFASPFASPFA.
  • Let's start with FloydFloyd. Clearly, pure triple-loop enumeration is bound to explode, but there can be an optimization in the loop because this is an undirected graph. iii to jjj and jjj to iii are the same, so the third-loop jjjj enumeration to IIII is OK, so ACACAC can be done.
  • There is also SPFASPFASPFA, in fact, this topic carries out ppp times SPFASPFA, enumerating each pasture as a concentrated point, summing up all the cattle's routes to reach the minimum value;

Code Jun

Lovely Floyd:
#include <bits/stdc++.h>
using namespace std;
int a[1000][1000];
int sum[1000];
int main()
{
	freopen("input.in","r",stdin);
	freopen("output.out","w",stdout);
	int n,m,c;
	scanf("%d %d %d",&n,&m,&c);
	for (int i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		sum[x]++;  //Count cattle numbers on Ranch x
	}
	memset(a,10,sizeof(a));  //initial value
	for (int i=1;i<=c;i++)
	{
		int x,y,v;
		scanf("%d %d %d",&x,&y,&v);
		a[x][y]=min(a[x][y],v);  //Adjacency matrix stores multiple edges
		a[y][x]=min(a[y][x],v);
	}
	for (int i=1;i<=m;i++) a[i][i]=0;  //initial value
	for (int k=1;k<=m;k++)
	 for (int i=1;i<=m;i++)
	  for (int j=1;j<i;j++)
	   if (a[i][k]+a[k][j]<a[i][j])  //iteration
	   {
	   		a[i][j]=a[i][k]+a[k][j];
	   		a[j][i]=a[i][k]+a[k][j];
	   }
	int ans=0xfffffff;
	for (int i=1;i<=m;i++)
	{
		int s=0;
		for (int j=1;j<=m;j++) s+=a[i][j]*sum[j];  //Accumulated distance
		ans=min(ans,s);  //Minimum
	}
	printf("%d",ans);
	return 0;
}
And then the handsome SPFA:
#include <bits/stdc++.h>
using namespace std;
int t=0,n,p,c;
int linkk[1500],dis[1500],vis[1500],q[10000],a[1500];
struct node
{
	int y,v,next;
}e[5005];
void insert(int x,int y,int v)
{
	e[++t].y=y; e[t].v=v;
	e[t].next=linkk[x]; linkk[x]=t; 
}
void SPFA(int k)  //SPFA Template
{
	memset(dis,10,sizeof(dis));  //initial value
	memset(vis,0,sizeof(vis));  //Empty the tag array, and vis[k] indicates whether point K is in the queue
	dis[k]=0;
	vis[k]=1;
	int head=1,tail=1;
	q[head]=k;  //Point k Entry
	for (head=1;head<=tail;head++)
	{
		int x=q[head];  //Remove the team leader
		for (int i=linkk[x];i>0;i=e[i].next)  //Adjacency table query
		{
			if (dis[x]+e[i].v<dis[e[i].y])  //iteration
			{
				dis[e[i].y]=dis[x]+e[i].v;
				if (vis[e[i].y]==0)  //If this point is not marked, mark, enter the team
				{
					vis[e[i].y]=1;
					q[++tail]=e[i].y;
				}
			}
		}
		vis[x]=0;  //Queue
	}
}
int main()
{
	freopen("input.in","r",stdin);
	freopen("output.out","w",stdout);
	scanf("%d %d %d",&n,&p,&c);
	for (int i=1;i<=n;i++) scanf("%d\n",&a[i]);
	for (int i=1;i<=c;i++)
	{
		int xx,yy,vv;
		scanf("%d %d %d",&xx,&yy,&vv);
		insert(xx,yy,vv);  //Adjacency table storage
		insert(yy,xx,vv);  //Bi-directional side
	}
	int ans=0xfffffff;
	for (int i=1;i<=p;i++)
	{
		SPFA(i);  //SPFA for each Ranch
		int s=0;
		for (int j=1;j<=n;j++) s+=dis[a[j]];  //Accumulated distance
		ans=min(ans,s);  //Minimum
	}
	printf("%d",ans);
	return 0;
}
Four original articles were published, 3 were praised, and 53 were visited
Private letter follow

Added by rklapwijk on Mon, 03 Feb 2020 04:44:20 +0200