题目描述:传送门
思路实现:
看见最短路径:我们可以联想到的算法有狄克斯特拉算法,弗洛伊德算法和bfs。实际上这道题目弗洛伊德算法比较合适,但此处作为一个bfs问题来求解。由于医院可能建立的点有1~n,因此分别以1~n为起点去进行bfs,分别求出最短路径,再从这些最短路径中挑选出最小的那条路径,该路径的起点则是医院的建立点。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 //虽然此处是树状结构,其实也能用邻接表的方式进行bfs,分别以每个结点当起点进行bfs 5 //建树方式也可以,只不过麻烦,bfs前还得建棵树 6 7 //新思路解决结点所在深度问题:设计一个结构体,保存当前结点的下标和深度,当前结点更新:上一层结点深度+1 8 int minn=1<<30; 9 int n=0; 10 int mapp[105][105]={0}; 11 bool v[105]; //用于判断某个点是否被访问过 12 int w[105]={0}; //存人口数 13 int bfs(int index){ //index下标, 14 memset(v,0,sizeof(v)); 15 int sum=0; 16 int size=1; //size表示的是当前层的结点数,每访问一个结点size--知道size减少到0代表当前层的结点全部已经遍历,此时深度step++ 17 //因为只有遍历完当前层最右边的点后深度step才会加1,同时也才进入下一层 18 int temp=0; //temp记录的是当前层的下一层的结点数,当size为0的时候,意味着进入下一层去遍历, 19 // 因此temp值赋给size,而temp情况重新累计下一层的结点数 20 queue<int> q; 21 q.push(index); //起点入队 22 v[index]=1; 23 int step=1; //记录bfs搜索层数 24 while(!q.empty()){ 25 int cur=q.front(); //cur是当前结点下标 26 q.pop(); 27 for(int i=1;i<=n;i++){ 28 if(mapp[cur][i]==0||v[i]) continue; 29 sum+=w[i]*step; 30 q.push(i); //入队 31 v[i]=1; 32 33 if(size>0){ 34 temp++; 35 } 36 } 37 size--; 38 if(size==0){ 39 size=temp; 40 temp=0; //又重新清0 41 step++; 42 } 43 } 44 return sum; 45 } 46 int main(){ 47 cin>>n; 48 for(int i=1;i<=n;i++){ 49 int v,u; 50 cin>>w[i]; 51 cin>>u>>v; 52 53 //再输入0的情况下也标了1 54 if(u) mapp[i][u]=1; //表示有连接 55 if(u) mapp[u][i]=1; //无向图 所以对称 56 if(v) mapp[i][v]=1; 57 if(v) mapp[v][i]=1; 58 } 59 60 for(int i=1;i<=n;i++){ //设每次bfs的起点是医院位置 61 minn=min(minn,bfs(i)); 62 } 63 cout<<minn; 64 return 0; 65 }
第二种bfs解法:只是将层数与顶点进行绑定方便操作
#include<iostream> #include<algorithm> #include<string.h> #include<queue> using namespace std; //这题是求最短距离问题 很适合bfs的使用 //并且求医院的建筑点 应该以每个节点为医院站点试试 int n; int mapp[105][105]={0}; //用于储存连接关系 int color[105]; //标记 int nodevalue[105]; //储存节点的数值 int dis[105]; //dis[i]表示节点为i作为医院建造点的总距离 int temp=0; typedef struct node{ int code; //编号 int l; //该点所在层数 }N; void bfs(int k){ color[k]=1; queue<N> q; N cur,next; cur.code=k; cur.l=0; q.push(cur); //编号为k的点入队 while(!q.empty()){ next=q.front(); q.pop(); // cout<<next.code<<endl; for(int i=1;i<=n;i++){ if((mapp[i][next.code]||mapp[next.code][i])&&!color[i]){ //i点不能被访问过 temp+=nodevalue[i]*(next.l+1); color[i]=1; //记得标记 N t; t.code=i; t.l=next.l+1; //代表上一层加1 q.push(t); } } } } int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>nodevalue[i]; int a,b; cin>>a>>b; if(a!=0){ mapp[i][a]=1; //无向 mapp[a][i]=1; } if(b!=0){ mapp[i][b]=1; mapp[b][i]=1; } } for(int i=1;i<=n;i++){ memset(color,0,sizeof(color)); temp=0; bfs(i); dis[i]=temp; } sort(dis+1,dis+n+1); //对dis[1]~dis[n]排序 cout<<dis[1]; return 0; }