德克萨斯长角牛 --最短路径
没事回顾一下最短路径算法。练练手。。
spfa 解法
#include <iostream> #include <cstdio> #include <queue> #include <cstring> using namespace std; struct node { int v,w,next; }; const int MAX=9999999999; node edge[32500]; int head[2510]; int cnt;//记录下biao int ts,te,t,c; void add(int u,int v,int w) { edge[cnt].w=w; edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++; } void SPFA() { int i,u,v;//u从Q中取出的点,v找到的点 int dis[2510]; int flag[2510]; bool vis[2510]; deque<int> que; fill(dis,dis+t+1,MAX); memset(flag,0,sizeof(flag)); memset(vis,false,sizeof(vis)); dis[ts]=0; que.push_back(ts); while(!que.empty()) { u=que.front(); que.pop_front(); vis[u]=false; for(i=head[u];i!=-1;i=edge[i].next) { v=edge[i].v; if(dis[v]>dis[u]+edge[i].w) { dis[v]=dis[u]+edge[i].w; if(!vis[v]) { vis[v]=true; flag[v]++; if(flag[v]>=t) return ; if(!que.empty()&&dis[v]<dis[que.front()]) que.push_front(v); else que.push_back(v); } } } } printf("%d\n",dis[te]); } int main() { scanf("%d%d%d%d",&t,&c,&ts,&te); memset(head,-1,sizeof(head)); cnt=0; int u,v,w; while(c--) { scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } SPFA(); return 0; }
dijkstra解法,直接套用的模板
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <queue> #define MAX 9999999 using namespace std; //pair 的first 保存的为最短距离, second保存的为顶点编号 typedef pair<int, int >P;//对组 不知道请自行百度 struct node { int v, w;//v 为到达的点, w为权重 int next;//记录下一个结构体的位置 ,就向链表的next功能是一样的 }; node edge[22003];//存所有的边,因为是无向图,所以*2 int cnt;//结构体的下标 int n, s, t;//n 点数,s 起点,t止点 int head[3203];//和链表的头指针数组是一样的。只不过此处head[u]记录的为最后加入 edge 的且与u相连的边在 edge 中的位置,即下标 void add(int u, int v, int w)//加边操作 { edge[cnt].v = v; edge[cnt].w = w; edge[cnt].next = head[u];//获得下一个结构体的位置 head[u] = cnt++;//记录头指针的下标 } void dijkstra() { int dis[3203];//最短路径数组 int i, v;//v保存从队列中取出的数的第二个数 也就是顶点的编号 priority_queue<P,vector<P>,greater<P> >que;//优先队列 从小到大 node e;//保存边的信息,为了书写方便 P p;//保存从队列取出的数值 fill(dis,dis+n+1,MAX);//初始化,都为无穷大 dis[s] = 0;//s—>s 距离为0 que.push(P(0,s));//放入距离 为0 点为s while(!que.empty()){ p = que.top();//取出队列中最短距离最小的对组 que.pop();//删除 v = p.second;//获得最短距离最小的顶点编号 if(dis[v] < p.first)//若取出的不是最短距离 continue;//则进行下一次循环 for(i=head[v];i!=-1;i=edge[i].next)//对与此点相连的所有的点进行遍历 { e = edge[i];//为了书写的方便。 if(dis[e.v]>dis[v]+e.w){//进行松弛 dis[e.v]=dis[v]+e.w;//松弛成功 que.push(P(dis[e.v],e.v));//讲找到的松弛成功的距离 和顶点放入队列 } } } printf("%d\n",dis[t]==MAX?-1:dis[t]);//输出结果 } int main() { int m, u, v, w; scanf("%d %d",&n,&m);//获取点数 边数 scanf("%d %d",&s,&t); cnt = 0;//结构体下标从0开始 memset(head,-1,sizeof(head));//初始化head[N]数组 while(m--){ scanf("%d %d %d",&u,&v,&w);//获取u,v,w(u,v) add(u,v,w);//加边 add(v,u,w);//加边 } //scanf("%d %d",&s,&t);//获取起止点 dijkstra(); return 0; }