【题解】cooking

来源:互联网 发布:网络基础知识ppt 编辑:程序博客网 时间:2024/06/08 15:39
cooking
Bessie喜欢为在外面的奶牛做晚餐,Bessie按响铃给他们一个信号叫他们进来就可以了。晚餐将在T (1 <= T <= 1,000,000)毫秒完成,而且Bessie强调那些想吃她晚餐的奶牛必须准时到。这些牛在F (1 <= F <= 500)各不同的草地标号为1~F用P(1 <= P<= 10,000)个双向的小路连接。Bessie在第1个草地, 给出一头牛走每一条小路所用的时间,问多少个草地上的奶牛可以在T毫秒内到Bessie 所在的草地,假设多头牛可以共享一条路。

【分析】
最短路径,Bellman_ford算法不解释

【例程wrong】
这个是一个神奇的“算法”,总之错了一个点。

#include<cstdio>
#include<cstring>
using namespace std;

const int oo=6666666;
int a,b,len,ans;
int num[501][501],dis[501];
int t,f,p;

int main()
{
memset(num,0,sizeof(num));
scanf("%d%d%d",&t,&f,&p);//time,field,path

for(int i=0;i<p;++i)
{
scanf("%d%d%d",&a,&b,&len);
num[a][b]=num[b][a]=len;
}

for(int i=1;i<=f;++i)
dis[i]=oo;
dis[1]=0;

for(int i=1;i<=f;++i)
{
for(int j=1;j<=f;++j)
if(num[i][j]>0&&dis[i]+num[i][j]<dis[j])
dis[j]=dis[i]+num[i][j];
}

ans=1;
for(int i=2;i<=f;++i)
if(dis[i]<=t)
++ans;

printf("%d\n",ans);
return 0;
}

【例程】
这才是正解。

#include<cstdio>
#include<cstring>
using namespace std;

const int oo=6666666;
int a,b,len,ans;
int dis[501];
int t,f,p;

struct hehe
{
int a,b,len;
};
hehe num[10001];

int main()
{
freopen("cooking.in","r",stdin);
freopen("cooking.out","w",stdout);

scanf("%d%d%d",&t,&f,&p);//time,field,path

for(int i=1;i<=p;++i)
{
scanf("%d%d%d",&num[i].a,&num[i].b,&num[i].len);
}

for(int i=1;i<=f;++i)
dis[i]=oo;
dis[1]=0;

for(int i=1;i<=f;++i)
{
for(int j=1;j<=p;++j)
{
if(dis[num[j].a]>dis[num[j].b]+num[j].len)
dis[num[j].a]=dis[num[j].b]+num[j].len;

if(dis[num[j].b]>dis[num[j].a]+num[j].len)
dis[num[j].b]=dis[num[j].a]+num[j].len;
}
}

ans=1;
for(int i=2;i<=f;++i)
if(dis[i]<=t)
++ans;

printf("%d\n",ans);
return 0;
}




【Bellman-Ford算法框架】
for 每个点u
for 点u旁边的每个点v
if dis[u]+len[u][v]<dis[v]
dis[v]=dis[u]+len[u][v];

注意if语句时要据题目做适当修改。

SPFA:修改刚更新的点加到队列中不断更新。一般使用循环队列,比Bellman-Ford算法大多数情况下要好。


0 0