P1364 医院设置(洛谷)

题目描述:传送门

 

思路实现:

  看见最短路径:我们可以联想到的算法有狄克斯特拉算法,弗洛伊德算法和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;
}

 

posted @ 2020-04-20 01:45  neverstopcoding  阅读(210)  评论(0编辑  收藏  举报