P1144 最短路计数

题目链接 https://www.luogu.com.cn/problem/P1144

第一道绿题。。(但是好像不应该是绿题。。)

本是想找几个最短路径做一下,然后去看了看lqs的博客,发现有这么个题(https://www.cnblogs.com/LQS-blog/p/16206505.html),他说:“当然,这类题也可以用dijkstra来处理,不过既然有了最优选择,何必去选择多余的呢,是吧”,欸我偏不,我就用dijkstra做,我还要用spfa做,最后我再用bfs,哈哈哈哈....

(以上不重要,划掉)


 

堆优化版dijkstra

无权无向确实是个特殊情况,所以说如果用除bfs的方法的话将权值都作为1就好了。

放AC代码

 1 #include<bits/stdc++.h>
 2 #define maxm 4000010
 3 #define maxn 1000010
 4 #define mod 100003
 5 using namespace std;
 6 int n,m,cnt;
 7 int dis[maxn];
 8 int head[maxn];
 9 bool vis[maxn];      //啊这,我也没用啊这
10 int js[maxn];//表示起点到某点的最短路径数目
11 
12 struct Edge
13 {
14     int v,w,next;
15 } edge[maxm];
16 
17 void add(int u,int v,int 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 struct node
26 {
27     int x,y;//起点 距离
28     bool operator < (const node &a) const
29     {//堆优化重载运算符,使大根堆变成小根堆
30         return y>a.y;
31     }
32 };
33 
34 void dijkstra()
35 {
36     memset(dis,0x3f,sizeof(dis));
37     dis[1]=0;
38     js[1]=1;
39     priority_queue<node> q;
40     q.push((node){1,0});
41     node a;
42     while(!q.empty())
43     {
44         a=q.top();//用node类型变量提取队首元素
45         int u=a.x;
46         int d=a.y;
47         q.pop();
48         for(int i=head[u]; i!=0; i=edge[i].next)
49         {
50             int v=edge[i].v;
51             int w=edge[i].w;
52             if(d+w==dis[v])//找到路线不同但权值相同的最短路
53                 js[v]=(js[v]+js[u])%mod;//边计算边模
54             if(dis[v]>dis[u]+w)
55             {
56                 dis[v]=dis[u]+w;
57                 js[v]=js[u];//找到一条更短的路径是,用它的前驱的js换它
58                 q.push((node){v,dis[v]});
59             }
60         }
61     }
62 }
63 
64 int main()
65 {
66     cin>>n>>m;
67     for(register int i=1; i<=m; i++)
68     {
69         int x,y;
70         cin>>x>>y;
71         add(x,y,1);
72         add(y,x,1);//无向图
73     }
74     dijkstra();
75     for(int i=1; i<=n; i++)
76         cout<<js[i]<<endl;
77     return 0;
78 }

 

真的不太理解重载运算符然后有时候还忘记怎么写就用另一种方式:将pair作为优先队列中的元素

1、优先队列默认大根堆排序

2、pair类型放入优先队列中总是先比较first的大小,如果相同再比较second的大小

那么我们可以将0减去dis数组的值作为pair中的键(first),将弧头作为值(second),通过这样巧妙的方式可以得到小根堆,就不需要重载运算符了。

放AC代码

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

 

SPFA

没啥特别的,板子罢了

放AC代码

 1 #include<bits/stdc++.h>
 2 #define maxm 4000010
 3 #define maxn 1000010
 4 #define mod 100003
 5 using namespace std;
 6 int n,m,cnt;
 7 int dis[maxn];
 8 int head[maxn];
 9 bool vis[maxn];
10 int js[maxn];
11 queue<int> q;
12 
13 struct Edge
14 {
15     int v,w,next;
16 } edge[maxm];
17 
18 void add(int u,int v,int w)
19 {
20     edge[++cnt].v=v;
21     edge[cnt].w=w;
22     edge[cnt].next=head[u];
23     head[u]=cnt;
24 }
25 
26 void spfa()
27 {
28     memset(dis,0x3f,sizeof(dis));
29     dis[1]=0, vis[1]=1, js[1]=1;
30     q.push(1);
31     while(!q.empty())
32     {
33         int a=q.front();
34         q.pop();
35         vis[a]=0;
36         for(int i=head[a]; i!=0; i=edge[i].next)
37         {
38             int v=edge[i].v;
39             int w=edge[i].w;
40             if(dis[v]==dis[a]+w)
41                 js[v]=(js[v]+js[a])%mod;
42             if(!vis[v] && dis[v]>dis[a]+w)
43             {//和上面两个代码不同的是两个if合二为一了
44                 dis[v]=dis[a]+w;
45                 js[v]=js[a];
46                 vis[v]=1;
47                 q.push(v);
48             }
49         }
50     }
51 }
52 
53 int main()
54 {
55     cin>>n>>m;
56     for(register int i=1; i<=m; i++)
57     {
58         int x,y;
59         cin>>x>>y;
60         add(x,y,1);
61         add(y,x,1);
62     }
63     spfa();
64     for(register int i=1; i<=n; i++)
65         cout<<js[i]<<endl;
66     return 0;
67 }

 

BFS

bfs确实适用于无权无向图,但是试过这几个方法之后发现其实差不多的事儿,没什么太大差别

放AC代码

 1 #include<bits/stdc++.h>
 2 #define maxm 4000010
 3 #define maxn 1000010
 4 #define mod 100003
 5 using namespace std;
 6 int n,m;
 7 int dis[maxn],js[maxn];
 8 bool vis[maxn];
 9 vector<int> g[maxn];
10 queue<int> q;
11 
12 void bfs()
13 {
14     dis[1]=0, vis[1]=1, js[1]=1;
15     q.push(1);
16     while(!q.empty())
17     {
18         int a=q.front();
19         q.pop();
20         for(unsigned int i=0; i<g[a].size(); i++)
21         {
22             int t=g[a][i];
23             if(!vis[t])
24             {
25                 vis[t]=1;
26                 dis[t]=dis[a]+1;
27                 q.push(t);
28             }
29             if(dis[t]==dis[a]+1)
30                 js[t]=(js[t]+js[a])%mod;
31         }
32     }
33 }
34 
35 int main()
36 {
37     cin>>n>>m;
38     for(register int i=1; i<=m; i++)
39     {
40         int x,y;
41         cin>>x>>y;
42         g[x].push_back(y);
43         g[y].push_back(x);
44     }
45     bfs();
46     for(register int i=1; i<=n; i++)
47         cout<<js[i]<<endl;
48     return 0;
49 }

 

posted @ 2022-05-03 20:46  爱吃虾滑  阅读(22)  评论(1编辑  收藏  举报