POJ 3159 Candies、
题意:n个小孩,m个比较(给你两个孩子代号a,b.然后c意味着a比b最多只能少c个糖果),问1和n之间差距最大的糖果数量、
思路:这是一个差分约束思路 不懂得:传送门,
转化一下就是一个SPFA求最短路的问题了、
参照了kuangbin大神的模板、
1 #include<cstring> 2 #include<cmath> 3 #include<cstdio> 4 const int qq=30005; 5 const int MAX=0x3f3f3f3f; 6 int head[qq]; //每个结点的头指针、 7 bool vis[qq]; //在队列中标记结点是否入队的标记数组、 8 int Q[qq]; 9 int dis[qq]; 10 int tol; 11 struct point 12 { 13 int v,to; 14 int next; 15 }graph[qq<<3]; 16 void add(int a,int b,int v) 17 { 18 graph[tol].to=b; 19 graph[tol].v=v; 20 graph[tol].next=head[a]; //链式前向星 21 head[a]=tol++; 22 } 23 void spfa(int start,int n) 24 { 25 int top=0; 26 for(int v=1;v<=n;++v){ 27 if(v==start){ 28 Q[top++]=v; 29 vis[v]=true; 30 dis[v]=0; 31 } 32 else{ 33 vis[v]=false; 34 dis[v]=MAX; 35 } 36 } 37 while(top){ //数组模拟队列 38 int u=Q[--top]; 39 vis[u]=false; 40 for(int i=head[u];i!=-1;i=graph[i].next){ 41 int v=graph[i].to; 42 if(dis[v]>dis[u]+graph[i].v){ 43 dis[v]=dis[u]+graph[i].v; 44 if(!vis[v]){ 45 vis[v]=true; 46 Q[top++]=v; 47 } 48 } 49 } 50 } 51 } 52 int main() 53 { 54 int n,m; 55 int a,b,c; 56 while(~scanf("%d%d",&n,&m)){ 57 tol=0; //记得初始化、 58 memset(head,-1,sizeof(head)); 59 while(m--){ 60 scanf("%d%d%d",&a,&b,&c); // b-a<=c 61 // 大-小<=c,有向边(小,大):C 62 add(a,b,c); 63 } 64 spfa(1,n); 65 printf("%d\n",dis[n]); 66 } 67 return 0; 68 }
针对为什么要添加一个vis数组谈一下自己的理解把、
SPFA算法+优先队列在处理问题,无论是最短路还是判断是否存在负权回路问题上都是很高效的、
那么vis数组的作用实际上要牵扯到SPFA算法是用的邻接表这种数据结构来进行的、
队列里面存的都是相应的顶点v
哪一些顶点呢、比如你先放一个初始顶点到队列里面去,那么把它弹出来更新当前顶点能到达的所有点已经到达每一个点的最短路径、
在能更新的情况下才会将此顶点放进队列里面去(这就是什么SPFA如此优化的原理),那么相应的每一个顶点在队列里面只要存在一个就行了、
因为只要存在一个的话就会更新它能到达的所有点、如果有多个的话由于此前有一个点已经更新过了、那么此时后面的都是做的无用功、
所以有一个vis数组的话可以降低一些无用功、
- -、表达能力不够理解程度也不够深、