前言
首先恭喜自己,终于写出了能在POJ上排第一名的代码。其次为自己惋惜下,判重时少了个“j!=x”的条件,找了n久才发现这个小bug,这要是在赛场上,肯定悔死了。首先用spfa做,怎么都找不出错误,甚至以为自己模板写错了,再用dijkstra做,发现依然wa,才觉得不是模板问题。
题目大意
哥伦布要从野人手里买20种货物。用以下四种种方法可以买到货物:
- 按货物的价格(以金币为单位)付足金币。
- 对于每个货物,可以用一个玻璃珠代替一个金币。
- 用等价的其他种类货物交换。
- 用价格更低的货物加上金币来交换。
问每种物品至少需要花多少金币才能买到。
思路
最短路,将每个物品抽象成节点,源点是虚拟的,源点与其他节点之间的边的权值就是物品价格。
注意物品价格相等时可以交换的条件,也就是说,此时两个节点应用一条权值为0的边相连。
代码
首先是用spfa写出的代码:
#include
#include
using namespace std;
#define datasize 20+1
#define maximum 2147483647
int map[datasize+1][datasize+1],d[datasize+1],mark[datasize+1],n,m;
void initialize_single_source(int s)
{
for(int i=1;id[u]+map[u][v])
d[v]=d[u]+map[u][v];
}
void spfa(int s)
{
initialize_single_source(s);
queue q;
for(int i=1;i<=n;i++)
mark[i]=false;
q.push(s);
mark[s]=true;
while(q.size())
{
int u=q.front();
q.pop();
mark[u]=false;
for(int i=1;i<=n;i++)
if(i!=u&&map[u][i]!=maximum)
{
int temp=d[i];
relax(u,i);
if(d[i]<temp&&!mark[i])
{
q.push(i);
mark[i]=true;
}
}
}
}
bool check(int x)
{
for(int i=2;i<=n;i++)
for(int j=2;j0;t--)
{
scanf("%d",&n);
n++;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
map[i][j]=maximum;
for(int i=0;i<n-1;i++)
{
int temp_1,temp_2;
scanf("%d%d",&temp_1,&temp_2);
map[1][temp_1+1]=temp_2-1;
}
scanf("%d",&m);
for(int i=0;i<m;i++)
{
int temp_1,temp_2,temp_3;
scanf("%d%d%d",&temp_1,&temp_2,&temp_3);
map[temp_1+1][temp_2+1]=temp_3;
}
for(int i=2;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(map[1][i]==map[1][j])
map[i][j]=map[j][i]=0;
spfa(1);
for(int i=0;i<n-1;i++)
printf("%d %d\n",i+1,d[i+2]);
int sum=0;
for(int i=2;i<=n;i++)
if(check(i))
sum++;
printf("%d\n",sum);
}
}
接着是dijkstra(堆优化)的做法:
#include
#include
using namespace std;
#define datasize 20+1
#define maximum 2147483647
int a[datasize+1],heap_size_a,v[datasize+1],map[datasize+1][datasize+1],length_a,n,m,result[datasize+1];
int parent(int i)
{
return i/2;
}
int left(int i)
{
return 2*i;
}
int right(int i)
{
return 2*i+1;
}
void min_heapify(int a[],int i)
{
int l=left(i),r=right(i),least;
if(l<=heap_size_a&&a[l]<a[i])
least=l;
else
least=i;
if(r<=heap_size_a&&a[r]=1;i--)
min_heapify(a,i);
}
int heap_extract_min(int a[])
{
int min=v[1];
result[v[1]]=a[1];
a[1]=a[heap_size_a];
v[1]=v[heap_size_a];
heap_size_a--;
min_heapify(a,1);
return min;
}
void heap_decrease_key(int a[],int i,int key)
{
a[i]=key;
while(i>1&&a[parent(i)]>a[i])
{
swap(a[i],a[parent(i)]);
swap(v[i],v[parent(i)]);
i=parent(i);
}
}
void initialize_single_source(int s)
{
length_a=n;
for(int i=1;iresult[i]+map[i][v[j]])
heap_decrease_key(a,j,result[i]+map[i][v[j]]);
}
void dijkstra(int s)
{
initialize_single_source(s);
build_min_heap(a);
while(heap_size_a>=1)
{
int u=heap_extract_min(a);
for(int i=1;i<=heap_size_a;i++)
if(map[u][v[i]]!=maximum)
relax(u,i);
}
}
bool check(int x)
{
for(int i=2;i<=n;i++)
for(int j=2;j0;t--)
{
scanf("%d",&n);
n++;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
map[i][j]=maximum;
for(int i=0;i<n-1;i++)
{
int temp_1,temp_2;
scanf("%d%d",&temp_1,&temp_2);
map[1][temp_1+1]=temp_2-1;
}
scanf("%d",&m);
for(int i=0;i<m;i++)
{
int temp_1,temp_2,temp_3;
scanf("%d%d%d",&temp_1,&temp_2,&temp_3);
map[temp_1+1][temp_2+1]=temp_3;
}
for(int i=2;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(map[1][i]==map[1][j])
map[i][j]=map[j][i]=0;
dijkstra(1);
for(int i=0;i<n-1;i++)
printf("%d %d\n",i+1,result[i+2]);
int sum=0;
for(int i=2;i<=n;i++)
if(check(i))
sum++;
printf("%d\n",sum);
}
}