USACO SECTION 3.2 Sweet Butter

Sweet Butter

Greg Galperin -- 2001

Farmer John has discovered the secret to making the sweetest butter in all of Wisconsin: sugar. By placing a sugar cube out in the pastures, he knows the N (1 <= N <= 500) cows will lick it and thus will produce super-sweet butter which can be marketed at better prices. Of course, he spends the extra money on luxuries for the cows.

FJ is a sly farmer. Like Pavlov of old, he knows he can train the cows to go to a certain pasture when they hear a bell. He intends to put the sugar there and then ring the bell in the middle of the afternoon so that the evening's milking produces perfect milk.

FJ knows each cow spends her time in a given pasture (not necessarily alone). Given the pasture location of the cows and a description of the paths the connect the pastures, find the pasture in which to place the sugar cube so that the total distance walked by the cows when FJ rings the bell is minimized. FJ knows the fields are connected well enough that some solution is always possible.

PROGRAM NAME: butter

INPUT FORMAT

  • Line 1: Three space-separated integers: N, the number of pastures: P (2 <= P <= 800), and the number of connecting paths: C (1 <= C <= 1,450). Cows are uniquely numbered 1..N. Pastures are uniquely numbered 1..P.
  • Lines 2..N+1: Each line contains a single integer that is the pasture number in which a cow is grazing. Cow i's pasture is listed on line i+1.
  • Lines N+2..N+C+1: Each line contains three space-separated integers that describe a single path that connects a pair of pastures and its length. Paths may be traversed in either direction. No pair of pastures is directly connected by more than one path. The first two integers are in the range 1..P; the third integer is in the range (1..225).

SAMPLE INPUT (file butter.in)

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

INPUT DETAILS

This diagram shows the connections geometrically:
          P2  
 P1 @--1--@ C1
     \    |\
      \   | \
       5  7  3
        \ |   \
         \|    \ C3
       C2 @--5--@
          P3    P4

OUTPUT FORMAT

  • Line 1: A single integer that is the minimum distance the cows must walk to a pasture with a sugar cube.

SAMPLE OUTPUT (file butter.out)

8

OUTPUT DETAILS:

Putting the cube in pasture 4 means: cow 1 walks 3 units; cow 2 walks 5
units; cow 3 walks 0 units -- a total of 8.

 

/*
ID: conicoc1
LANG: C
TASK: butter
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define INIFINITY 210000

int Milks,Pastures,Path;
int Map[801][801];   //邻接矩阵 
int Dist[801];       //SPFA中到起始点的距离 
int Link[801][801]; //邻接表 
int MilkIn[501];    //牛所在的牧场 
int Queue[801];
int InQueue[801];
int front=0;rear=0;
int MinDistSum;

void Enqueue(int Vertex)
{
	Queue[rear++]=Vertex;
	rear%=801;	
}

int Dequeue()
{
	int Vertex;
	Vertex=Queue[front++];
	front%=801;
	return Vertex;
	
}

int main()
{
	FILE *fin,*fout;
	fin=fopen("butter.in","r");
	fout=fopen("butter.out","w");
	int i,j,k,Sum,dis,cow;
	int V,W;
	memset(InQueue,0,sizeof(InQueue));
	memset(Link,0,sizeof(Link));
	
	fscanf(fin,"%d %d %d",&Milks,&Pastures,&Path);
	for(i=1;i<=Pastures;i++)
		for(j=1;j<=Pastures;j++){
			Map[i][j]=INIFINITY;
			if(i==j)
				Map[i][j]=0;
		}
	
	for(i=1;i<=Milks;i++)
		fscanf(fin,"%d",&MilkIn[i]);
	for(i=1;i<=Path;i++){
		fscanf(fin,"%d %d",&j,&k);
		fscanf(fin,"%d",&dis);
		if(dis<Map[k][j]){
	 		Map[k][j]=Map[j][k]=dis;
	 		Link[k][++Link[k][0]]=j;
	 		Link[j][++Link[j][0]]=k;
		}	
	}
	
	for(i=1;i<=Milks;i++){
		for(j=1;j<=Pastures;j++)
			Dist[j]=INIFINITY;
		Enqueue(MilkIn[i]);
		Dist[MilkIn[i]]=0;
		InQueue[MilkIn[i]]=1;
		while(front!=rear){
			V=Dequeue();
			for(j=1;j<=Link[V][0];j++){
				W=Link[V][j];
				if(Dist[W]>Dist[V]+Map[V][W]){
					Dist[W]=Dist[V]+Map[V][W];
					if(!InQueue[W]){
						Enqueue(W);
						InQueue[W]=1;
					}		
				}
			}
			InQueue[V]=0;
		}		
		for(j=1;j<=Pastures;j++){
			if(Dist[j]<Map[MilkIn[i]][j])
				Map[MilkIn[i]][j]=Dist[j];
		}	
	}
	
	MinDistSum=INIFINITY*Milks;
	for(i=1;i<=Pastures;i++){
		Sum=0;
		for(j=1;j<=Milks;j++){
			Sum+=Map[MilkIn[j]][i];
		}
		if(Sum<MinDistSum)
			MinDistSum=Sum;
	}
	fprintf(fout,"%d\n",MinDistSum);
	return 0;
}
	
	


 

一开始用的Floyd果断超时了

这个是SPFA+静态邻接表

 

Analysis里用的Dijkstra+Heap优化

上次写过一次堆优化,各种蛋疼,这次看了给的代码,发现自己以前写的那个是什么东西。。想吐了。。

 

 

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
 
#define BIG 1000000000
#define MAXV 800
#define MAXC 500
#define MAXE 1450
 
int cows;
int v,e;
 
int cow_pos[MAXC];
int degree[MAXV];
int con[MAXV][MAXV];
int cost[MAXV][MAXV];
 
int dist[MAXC][MAXV];
 
int heapsize;
int heap_id[MAXV];
int heap_val[MAXV];
int heap_lookup[MAXV];
bool fixed[MAXV];
 
bool validheap(void)
{
	int i;
	for(i = 0; i < heapsize; ++i){
		if(!(0 <= heap_id[i] && heap_id[i] < v)){
			return(false);
		}
		if(heap_lookup[heap_id[i]] != i){
			return(false);
		}
	}
	return(true);
}
 
void heap_swap(int i, int j){
	int s;
 
	s = heap_val[i];
	heap_val[i] = heap_val[j];
	heap_val[j] = s;
 
	heap_lookup[heap_id[i]] = j;
 
	heap_lookup[heap_id[j]] = i;
 
	s = heap_id[i];
	heap_id[i] = heap_id[j];
	heap_id[j] = s;
 
}
 
void heap_up(int i){
	if(i > 0 && heap_val[(i-1) / 2] > heap_val[i]){
		heap_swap(i, (i-1)/2);
		heap_up((i-1)/2);
	}
}
 
void heap_down(int i){
	int a = 2*i+1;
	int b = 2*i+2;
 
	if(b < heapsize){
		if(heap_val[b] < heap_val[a] && heap_val[b] < heap_val[i]){
			heap_swap(i, b);
			heap_down(b);
			return;
		}
	}
	if(a < heapsize && heap_val[a] < heap_val[i]){
		heap_swap(i, a);
		heap_down(a);
	}
}
 
int main()
{
	int i, j, k;
	int p, q;
	int best = BIG, total;
	freopen("butter.in", "r", stdin);
	freopen("butter.out", "w", stdout);
	scanf("%d %d %d", &cows, &v, &e);
	for(i = 0; i < cows; ++i){
		scanf("%d", &cow_pos[i]);
		--cow_pos[i];
	}
	memset(degree, 0, sizeof(degree));
	for(i = 0; i < e; ++i){
		int a,b,c;
		scanf("%d %d %d", &a, &b, &c);
		--a, --b;
 
		con[a][degree[a]] = b;
		cost[a][degree[a]] = c;
		++degree[a];
 
		con[b][degree[b]] = a;
		cost[b][degree[b]] = c;
		++degree[b];
	}
 
	for(i = 0; i < cows; ++i){
		heapsize = v;
		for(j = 0; j < v; ++j){
			heap_id[j] = j;
			heap_val[j] = BIG;
			heap_lookup[j] = j;
		}
		heap_val[cow_pos[i]] = 0;
		heap_up(cow_pos[i]);
 
		memset(fixed, false, v);
		for(j = 0; j < v; ++j){
			p = heap_id[0];
			dist[i][p] = heap_val[0];
			fixed[p] = true;
			heap_swap(0, heapsize-1);
			--heapsize;
			heap_down(0);
 
			for(k = 0; k < degree[p]; ++k){
				q = con[p][k];
				if(!fixed[q]){
					if(heap_val[heap_lookup[q]] > dist[i][p] + cost[p][k]){
						heap_val[heap_lookup[q]] = dist[i][p] + cost[p][k];
						heap_up(heap_lookup[q]);
					}
				}
			}
 
		}
	}
 
	for(i = 0; i < v; ++i){
		total = 0;
		for(j = 0; j < cows; ++j){
			total += dist[j][i];
		}
		if(best > total){
			best = total;
		}
	}
 
	printf("%d\n", best);
 
	return(0);
}


还是忍不住贴一下,以后看看

他这边邻接表的邻边数另外开了一个数组,感觉不方便

但是堆优化可以看看开了3个数组,heap_id,heap_val,heap_lookup ..然后。。然后就看不懂了。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值