NYOJ1274
知识点1
这个题如果不想用指针,可以用数组的方法去实现邻接链表。
先打个比方:
0 1 2 3 4 5 数组下标
-1 0 4 -1 3 -1 存的内容
可以表示为:
点 1存下标0 0与任何点都不连接,即链接结束 0 1是有关系的
点 2存下标4 , 4 存下标3, 3存下标-1即链接结束 2 3 4是有关系的一条链
点 5独立。
我们可以把每一条链对应的一个点关联起来,就可以表示邻接链表了。
再开一个数组 存储每一天链的开头,如 a【0】 = 2;联系本题,则表示 点0 与2 3 4一条链有关联,
及2 3 4所在的位置不仅存着链接下一个链的 next 还有本 位置对应的一个点表示与0点可通路的点信息。
点击细节->更详细的数组表示邻接表的思想(初学者必看)
知识点2
我个人认为本题不需要用数组记录走过的点,因为即使出现环路状况,因为本题特点 越乘越小的性质(与最短路 成环路越加越大),都是背离答案目标的,因此不需要设置。用队列间接地实现了动态规划,由于只
有 新更新的点 进行更新 新的路径,减少循环次数了。
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
int first[50001];
queue<int> a;
double dis[10001];
struct node
{
int b,e;
double w;
int next;
}edge[50001];
int num;
void add_edge(int b, int e ,double w)
{
edge[num].b = b;
edge[num].e = e;
edge[num].w = w;
edge[num].next = first[b];
first[b] = num;
num++;
}
void SPFA()
{
int i,begin,b,e;
memset(dis,0,sizeof(dis));
a.push(1);
begin = first[1];
b = edge[begin].b;
dis[b] = 1.0;
while(!a.empty())
{
begin = a.front();
a.pop() ;
if(b == -1)continue;
b = begin;
for(i = first[begin] ; i != -1; i = edge[i].next)
{
e = edge[i].e;
if(dis[e] < dis[b]*edge[i].w)
{
dis[e] = dis[b]*edge[i].w;
a.push(e);
}
}
}
}
int main()
{
int T,n,m,i,b,e;
double w;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
num = 0;
memset(first,-1,sizeof(first));
memset(vis,0,sizeof(vis));
for(i = 0;i<m;i++)
{
scanf("%d %d %lf",&b,&e,&w);//lf细节
add_edge(b,e,w/100);
add_edge(e,b,w/100);
}
SPFA();
printf("%.6f\n",dis[n]*100);
}
return 0;
}