SDUTOJ 2021级ACM班&2022年寒假集训《数据结构》专题10--最短路

A - 图结构练习——最短路径

dijkstra朴素版和堆优化版的模板,权当复习了

因为是循环输入,一开始写初始化函数的时候没有把head和vis也初始化掉,导致TLE了。

左朴素版,右优化版

朴素版:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,cnt,cur;
 4 int head[210];
 5 int dis[210];
 6 bool vis[210];
 7 
 8 struct node
 9 {
10     int v,w,next;
11 } edge[100000];
12 
13 void add(int u,int v,int w)
14 {
15     edge[++cnt].v=v;
16     edge[cnt].w=w;
17     edge[cnt].next=head[u];
18     head[u]=cnt;
19 }
20 
21 void init(int n)
22 {
23     for(int i=1; i<=n; i++)
24     {
25         dis[i]=INT_MAX;
26         head[i]=0;
27         vis[i]=0;
28     }
29     dis[1]=0;
30     cur=1;
31     cnt=0;
32 }
33 
34 void dijkstra(int n)
35 {
36     for(int i=head[1]; i!=0; i=edge[i].next)
37             dis[edge[i].v]=min(dis[edge[i].v],edge[i].w);
38     while(!vis[cur])
39     {
40         vis[cur]=true;
41         for(int i=head[cur]; i!=0; i=edge[i].next)
42         {
43             if(!vis[edge[i].v] && dis[edge[i].v]>dis[cur]+edge[i].w)
44                 dis[edge[i].v]=dis[cur]+edge[i].w;
45         }
46         int minn=INT_MAX;
47         for(int i=1; i<=n; i++)
48         {
49             if(!vis[i] && dis[i]<minn)
50             {
51                 minn=dis[i];
52                 cur=i;
53             }
54         }
55     }
56     cout<<dis[n]<<endl;
57 }
58 
59 int main()
60 {
61     while(cin>>n>>m)
62     {
63         init(n);
64         if(m!=0)
65         {
66             for(int i=1; i<=m; i++)
67             {
68                 int u,v,w;
69                 cin>>u>>v>>w;
70                 add(u,v,w);
71                 add(v,u,w);
72             }
73             dijkstra(n);
74         }
75         else cout<<"0"<<endl;
76     }
77     return 0;
78 }

优化版:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,cnt,cur;
 4 int head[20010];
 5 int dis[20010];
 6 bool vis[20010];
 7 priority_queue< pair<int,int>,vector< pair<int,int> >,greater<pair<int,int> > >q;
 8 
 9 struct node
10 {
11     int v,w,next;
12 }edge[1000010];
13 
14 void add(int u,int v,int w)
15 {
16     edge[++cnt].v=v;
17     edge[cnt].w=w;
18     edge[cnt].next=head[u];
19     head[u]=cnt;
20 }
21 
22 void init(int n)
23 {
24     for(int i=1; i<=n; i++)
25     {
26         dis[i]=INT_MAX;
27         head[i]=0;
28         vis[i]=0;
29     }
30     dis[1]=0;
31     cnt=0;
32 }
33 
34 void dijkstra(int n)
35 {
36     q.push(make_pair(0,1));
37     while(!q.empty())
38     {
39         int point=q.top().second;
40         q.pop();
41         if(vis[point]) continue;
42         vis[point]=1;
43         for(int i=head[point]; i!=0; i=edge[i].next)
44         {
45             if(dis[edge[i].v]>dis[point]+edge[i].w)
46             {
47                 dis[edge[i].v]=dis[point]+edge[i].w;
48                 q.push(make_pair(dis[edge[i].v],edge[i].v));
49             }
50         }
51     }
52     cout<<dis[n]<<endl;
53 }
54 
55 int main()
56 {
57     while(cin>>n>>m)
58     {
59         init(n);
60         for(int i=1; i<=m; i++)
61         {
62             int u,v,w;
63             cin>>u>>v>>w;
64             add(u,v,w);
65             add(v,u,w);
66         }
67         dijkstra(n);
68     }
69     return 0;
70 }

 

B - 最短路径问题

题目链接 https://acm.sdut.edu.cn/onlinejudge3/contests/3988/problems/B

n<=100,用floyd就可。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m;
 4 double mapp[150][150];
 5 int mapx[150],mapy[150];
 6 void floyd()
 7 {
 8     for(int k=1; k<=n; k++)
 9     {
10         for(int i=1; i<=n; i++)
11         {
12             for(int j=1; j<=n; j++)
13             {
14                 if(mapp[i][j]>mapp[i][k]+mapp[k][j])
15                     mapp[i][j]=mapp[i][k]+mapp[k][j];
16             }
17         }
18     }
19 }
20 
21 int main()
22 {
23     cin>>n;
24     for(int i=1; i<=n; i++)
25     {
26          for(int j=1; j<=n; j++)
27          {
28              mapp[i][j]=i==j?0:INT_MAX;
29          }
30      }
31     for(int i=1; i<=n; i++)
32         cin>>mapx[i]>>mapy[i];
33     cin>>m;
34     for(int i=1; i<=m; i++)
35     {
36         int u,v; 
37         double w;
38         cin>>u>>v;
39         w=sqrt((double)(mapx[v]-mapx[u])*(double)(mapx[v]-mapx[u])+(double)(mapy[v]-mapy[u])*(double)(mapy[v]-mapy[u]));
40         if(mapp[u][v]>w)  mapp[u][v]=mapp[v][u]=w;
41     }
42     floyd();
43     int s,t;
44     cin>>s>>t;
45     printf("%.2lf\n",mapp[s][t]);
46     return 0;
47 } 

 

C - C--最短路

题目链接 https://acm.sdut.edu.cn/onlinejudge3/contests/3988/problems/C

用的dijkstra堆优化版

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,s,e;
 4 int cnt;
 5 int head[500050];
 6 int dis[500050];
 7 bool vis[500050];
 8 priority_queue< pair<int,int>,vector< pair<int,int> >,greater<pair<int,int> > >q;
 9 
10 struct node
11 {
12     int v,w,next;
13 }edge[5000500];
14 
15 void add(int u,int v,int w)
16 {
17     edge[++cnt].v=v;
18     edge[cnt].w=w;
19     edge[cnt].next=head[u];
20     head[u]=cnt;
21 }
22 
23 void init(int n)
24 {
25     for(int i=1; i<=n; i++)
26     {
27         dis[i]=INT_MAX;
28         vis[i]=0;
29         head[i]=0;
30     }
31     cnt=0;
32 }
33 
34 void dijkstra(int s,int e)
35 {
36     dis[s]=0;
37     q.push(make_pair(0,s));
38     while(!q.empty())
39     {
40         int point=q.top().second;
41         q.pop();
42         if(vis[point]) continue;
43         vis[point]=1;
44         for(int i=head[point]; i!=0; i=edge[i].next)
45         {
46             if(dis[edge[i].v]>dis[point]+edge[i].w)
47             {
48                 dis[edge[i].v]=dis[point]+edge[i].w;
49                 q.push(make_pair(dis[edge[i].v],edge[i].v));
50             }
51         }
52     }
53     cout<<dis[e]<<endl;
54 }
55 
56 int main()
57 {
58     while(cin>>n>>m)
59     {
60         init(n);
61         for(int i=1; i<=m; i++)
62         {
63             int u,v,w;
64             cin>>u>>v>>w;
65             add(u,v,w);
66             add(v,u,w);
67         }
68         cin>>s>>e;
69         dijkstra(s,e);
70     }
71     return 0;
72

 

D - 最短路径(更于——5.9 21:45)

我真服了这个老六啊......调试了整整一个下午都不对,都快给电脑砸了。晚上寻思着写完论文怎么今晚也给整出来吧,结果刚才发现第50行定义 w 忘记用 long long ,服了我真。
这个题,在上面那个题的基础上多了判断是否为x倍数。大体思路是用 SPFA ,增加一个维度,储存步数对 x 取模,最后输出对 x 取模后是 0 的终点距离即可。
 1 #include<bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 using namespace std;
 4 int T,n,m,s,t,x,cnt;
 5 int head[110];
 6 long long dis[110][12];
 7 bool vis[110];
 8 queue<int>q;
 9 
10 struct node
11 {
12     int v;
13     long long w;
14     int next;
15 } edge[10010];
16 
17 void add(int u,int v,long long w)
18 {
19     edge[++cnt].v=v;
20     edge[cnt].w=w;
21     edge[cnt].next=head[u];
22     head[u]=cnt;
23 }
24 
25 void init(int n)
26 {
27     cnt=0;
28     memset(head,0,sizeof(head));
29     memset(vis,0,sizeof(vis));
30     for(int i=0; i<=n; i++)
31         for(int j=0; j<=11; j++)
32             dis[i][j]=INF;
33 }
34 
35 void spfa()
36 {
37     while(!q.empty())
38         q.pop();
39     vis[s]=1;
40     dis[s][0]=0;
41     q.push(s);
42     while(!q.empty())
43     {
44         int u=q.front();
45         q.pop();
46         vis[u]=0;
47         for(int i=head[u]; i!=0; i=edge[i].next)
48         {
49             int v=edge[i].v;
50             long long w=edge[i].w;
51             for(int j=0; j<x; j++)
52             {
53                 if(dis[u][j]!=INF && (dis[v][(j+1)%x]>dis[u][j]+w || dis[v][(j+1)%x]==INF))
54                 {
55                     dis[v][(j+1)%x]=dis[u][j]+w;
56                     if(!vis[v])
57                     {
58                         vis[v]=1;
59                         q.push(v);
60                     }
61                 }
62             }
63         }
64     }
65     if(dis[t][0]==INF) cout<<"No Answer!"<<endl;
66     else cout<<dis[t][0]<<endl;
67 }
68 
69 int main()
70 {
71     cin>>T;
72     while(T--)
73     {
74         cin>>n>>m;
75         init(n);
76         for(int i=1; i<=m; i++)
77         {
78             int u,v;
79             long long w;
80             cin>>u>>v>>w;
81             add(u,v,w);
82         }
83         cin>>s>>t>>x;
84         spfa();
85     }
86     return 0;
87 }

 

E - 数据结构实验之图论七:驴友计划(更于——5.10)

题目链接 https://acm.sdut.edu.cn/onlinejudge3/contests/3988/problems/E

2<=N<=500 ,最喜欢用floyd了!

多定义一个 value 数组保存过路费就好了。

 1 #include<bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 using namespace std;
 4 int n,m,s,d;
 5 int gra[510][510];
 6 int value[510][510];
 7 
 8 void floyd()
 9 {
10     for(int k=0; k<n; k++)
11     {
12         for(int i=0; i<n; i++)
13         {
14             for(int j=0; j<n; j++)
15             {
16                 if(i!=j)
17                 {
18                     if(gra[i][j]>gra[i][k]+gra[k][j])
19                     {
20                         gra[i][j]=gra[i][k]+gra[k][j];
21                         value[i][j]=value[i][k]+value[k][j];
22                     }
23                     if(gra[i][j]==gra[i][k]+gra[k][j])
24                     {
25                         if(value[i][j]>value[i][k]+value[k][j])
26                             value[i][j]=value[i][k]+value[k][j];
27                     }
28                 }
29             }
30         }
31     }
32 }
33 
34 int main()
35 {
36     int T;
37     cin>>T;
38     while(T--)
39     {
40         cin>>n>>m>>s>>d;
41         for(int i=0; i<n; i++)
42         {
43             for(int j=0; j<n; j++)
44             {
45                 if(i==j) gra[i][j]=value[i][j]=0;
46                 else gra[i][j]=value[i][j]=INF;
47             }
48         }
49         for(int i=0; i<m; i++)
50         {
51             int u,v,w,val;
52             cin>>u>>v>>w>>val;
53             gra[u][v]=gra[v][u]=w;
54             value[u][v]=value[v][u]=val;
55         }
56         floyd();
57         cout<<gra[s][d]<<" "<<value[s][d]<<endl;
58     }
59     return 0;
60 }

 

F - 人活着系列之芳姐和芳姐的猪

题目链接 https://acm.sdut.edu.cn/onlinejudge3/problems/2929

首先看到结点的数据范围 2<=m<=600 ,直接想到 floyd 。然后读题,可以看出是多源最短路问题,需要算出每个点到每个点的最短路,起始点和终点都不固定。

 

 1 #include<bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 using namespace std;
 4 int n,m,k;
 5 int s[610];
 6 int mapp[610][610];
 7 
 8 void floyd()
 9 {
10     for(int k=1; k<=m; k++)
11         for(int i=1; i<=m; i++)
12             for(int j=1; j<=m; j++)
13                 mapp[i][j]=min(mapp[i][j],mapp[i][k]+mapp[k][j]);
14 }
15 
16 int main()
17 {
18     cin>>n>>m>>k;
19     for(int i=1; i<=n; i++)
20         cin>>s[i];
21     memset(mapp,INF,sizeof(mapp));
22     for(int i=1; i<=610; i++)
23         mapp[i][i]=0;
24     for(int i=1; i<=k; i++)
25     {
26         int u,v,w;
27         cin>>u>>v>>w;
28         if(w<mapp[u][v])
29             mapp[u][v]=mapp[v][u]=w;
30     }
31     int minn=INF;
32     floyd();
33     for(int i=1; i<=m; i++)
34     {
35         int sum=0;
36         for(int j=1; j<=n; j++)
37         {
38             sum+=mapp[i][s[j]];
39         }
40         if(sum<minn)
41             minn=sum;
42     }
43     cout<<minn<<endl;
44     return 0;
45 }

 

 

 

posted @ 2022-05-08 11:27  爱吃虾滑  阅读(38)  评论(0)    收藏  举报