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 }