700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > %大赛D--链式前向星+SPFA(BFS)+各种数据类型+各种最短路复习

%大赛D--链式前向星+SPFA(BFS)+各种数据类型+各种最短路复习

时间:2021-11-15 19:17:42

相关推荐

%大赛D--链式前向星+SPFA(BFS)+各种数据类型+各种最短路复习

单源最短路模板题,这里尝试用SPFA,但有几点细节:

①不能用邻接矩阵,开不下1e5*1e5的二维数组;邻接表vector<p>G[maxn]或链式前向星

②注意用longlong,而且INF定义为LONG_LONG_MAX(不要手打整数,因为默认为int,也可强制类型转换(1e16))

复习:long double,unsigned long long...log

1e16 double

999999999999999... int(溢出)

③最短路算法复习:

a.Dijkstra

一开始觉得和Prim很像,都用到贪心,而且选好点后,更新与这点相关(可到达)的数据,但是贪心的对象有细微不同。

Prim是dis一维数组(表示目前已加入生成树的点,到其相邻结点的权值的最小值)进行贪心,没有dp的思想;

Dijkstra对松弛操作的dis一维数组(表示起点到该点的最小距离,还要加上前面已经得到的最小距离,而前面得到局部最小距离,必须也是全局最小距离,这是算法成立的关键,也是为什么Dijkstra只支持非负边,这里最优子结构的思想,类似dp)贪心,取出最小所在的的结点P,然后对该点P邻点(这里类似广搜),更新数据,vis标记该点P,最后往复上述操作直到所有vis的点被标记上。

dis 1 2 3 4 5 6 (绿色表示当前取得,红色表示vis标记过已经取过的点,蓝色代表更新的点)

0 7 9∞ ∞14

0 7 9 ∞ ∞ 14

0 7 9 22 ∞ 14

0 7 9 20 ∞ 11

0 7 9 20 ∞ 11

0 7 9 20 20 11

...

0 7 9 20 20 11

具体思想看看这篇博客:

点击打开链接

b.Floyd

联想到之前离散数学学的传递闭包Warshall求法:

①k 1-n 找到第k列

②i 1-n 找到值为1的行,下标i→if(a[i][k]==1)→则执行③j 1-n a[i][j]=a[k][j]

用到三重循环,Floyd与之类似,只不过思想有所改变:

找到第k个结点作为中间点,比较i到j直达的距离和加了中间点k距离。

c.

最近市面出现了一款全新的游戏,Absolute Counter Online,简称ACO。Asuna跟她的男票Kirito也都跑去玩这个了。

把Kirito传送了K次之后,Asuna终于气消了。。。

最新情报,在这个游戏里,也有传说中的圣剑excalibur,俗称咖喱棒。作为耍剑的高手Kirito自然不能放过这么好的一个机会。游戏里有N那个城市,同时有M条道路连接不同的两个城市,经过不同的道路耗费的时间是不同的。当前Kirito在编号为S的城市,得到的消息是圣剑藏在编号为T的城市中。因为游戏中其他玩家也想抢圣剑,所以Kirito希望用最快的速度到达城市T。而Asuna发现,每个城市中都会有一个传送用的魔法阵,可以快速将他们传送到任意一个城市(没错,这次他们是两人一起传送),不同的魔法阵传送的用时也不同。

Input

多组数据,EOF结尾。

每组数据先输入两个整数N和M,表示有N个城市及M条无向边。

2 <= N <= 100000

1 <= M <= 200000

接下来一行,输入N个整数,第i个数字表示城市i的魔法阵,传送的用时Ui, 1<=Ui<=1000000000。

接下来输入两个整数S和T,表示Kirito他们所在城市,以及圣剑所在城市,1<=S,T<=N 且 S!=T。

接下来M行,每行三个整数X, Y, W,表示一条连接X和Y两个城市的无向边,通过这条边的耗时为W,1<=X,Y<=N, X!=Y, 1<=W<=1000000000。

Output

对于每组数据,输出格式为:“Case #k: u”,k表示第k组数据,从1开始,u表示最短用时。

Sample Input

4 31 2 3 41 41 2 12 3 13 4 14 310 2 3 41 42 1 12 3 13 4 1

Sample Output

Case #1: 1Case #2: 3

#include <stdio.h> #include <cstring> #include <iostream> #include <algorithm> #include <queue> using namespace std; const int maxn=300001; const long long inf =(long long)(1e16); //不能直接打数字!!!默认是int会WAstruct edge { int from,to,next; long long w; }e[1000001]; int head[maxn]; int vis[maxn]; int vis2[maxn]; long long dist[maxn]; long long mo[maxn]; int n,m,t; void add(int i,int j,long long w) { e[t].from=i; e[t].to=j; e[t].w=w; e[t].next=head[i]; head[i]=t++; } long long spfa(int s,int end,int n) { queue <int> q; for(int i=1;i<=n;i++) dist[i]=inf; memset(vis,false,sizeof(vis)); memset(vis2,false,sizeof(vis2)); q.push(s); dist[s]=0; while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=false; for(int i=head[u];i!=-1;i=e[i].next) { int v=e[i].to; if(dist[v]>dist[u]+e[i].w) { dist[v]=dist[u]+e[i].w; if(!vis[v]) { vis[v]=true; q.push(v); } }} } long long res= dist[end];for(int i=1;i<=n;i++){res=min(res,dist[i]+mo[i]);}return res;} int main() { int a,b,s,e; long long c;int cnt=1; // scanf("%d%d",&n,&m); while(cin>>n>>m){memset(mo,0,sizeof(mo));t=0; memset(head,-1,sizeof(head)); //memset(dist,0,sizeof(dist));for(int i=1;i<=n;i++){scanf("%lld",&mo[i]);}scanf("%d%d",&s,&e); while(m--) { scanf("%d%d%lld",&a,&b,&c); add(a,b,c); add(b,a,c);} long long res1= spfa(s,e,n); printf("Case #%d: %lld\n",cnt,res1);cnt++;}return 0; }

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。