【6.10校內test】T2 醫院設置

醫院設置【題目連接】node

感受我超廢ios


我是一個連floyd都不會寫了的靈魂OI選手qwq(考場上寫了半天spfa而後寫炸了(微笑))算法

floyd的暴力:數組

1.先建樹:用鄰接矩陣存。存以前記得先初始化爲INF學習

   注意是無向圖。而後注意本身到本身的狀況dis值=0;spa

2.跑一遍floyd,求最短路;3d

3.枚舉每一個點建醫院,至關於求每一個點做爲源點的單源最短路,而後乘people數,比較大小,輸出最小的一個;code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<string>
const int INF=100000007;

using namespace std;

int n,dis[110][110],sum;
struct people{
    int num,l,r;
}p[110];

int main(){
    
    memset(dis,INF,sizeof(dis));
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d",&p[i].num,&p[i].l,&p[i].r);
        if(p[i].l) dis[i][p[i].l]=1,dis[p[i].l][i]=1;
        if(p[i].r) dis[i][p[i].r]=1,dis[p[i].r][i]=1;
        dis[i][i]=0;
    }
    
    for(int k=1;k<=n;k++){//floyd 
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++)
            if(dis[i][j]>dis[i][k]+dis[k][j]) dis[i][j]=dis[i][k]+dis[k][j];
        }
    }
    int minn=INF;
    for(int i=1;i<=n;i++){//求單源最短路+乘起來; 
        sum=0;
        for(int j=1;j<=n;j++)
          sum+=dis[i][j]*p[j].num;
        if(sum<minn) minn=sum;
    }
    cout<<minn<<endl;
    return 0;
}

又是water_lift的非暴力解法:blog

首先建樹,water_lift是利用了「父子」關係建成的樹,定義一個隊列,依次枚舉以每一個結點作根的狀況,而後修改權值,隊列

開二維數組dis[i][j]和bool判斷數組vis[i],分別表示從i=>j的權值大小,是否已經計算過了,而後再跑二重循環,將dis[i][j]與對應的人數相乘,比較取最小的(好像ans是water_lift用來記錄哪一個結點是根的

撒花☆☆☆☆

#include <iostream>
#include <queue>
#include <cstring>
#include <limits.h>
using namespace std;
int n;
int lch[101], rch[101], fa[101], sum[101];
int dis[101][101];
bool vis[101];
int root;
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> sum[i] >> lch[i] >> rch[i];
        fa[lch[i]] = fa[rch[i]] = i;
    }
    for (int i = 1; i <= n; i++)//好像也沒用 
    {
        root = i;
    }
    for (int i = 1; i <= n; i++)
    {
        queue<int> q;
        q.push(i);
        memset(vis, 0, sizeof(vis));
        vis[i] = 1;
        dis[i][i] = 0;
        while (!q.empty())
        {
            int node = q.front();
            q.pop();
            if (lch[node] && !vis[lch[node]])//保證左兒子右兒子以及父親都被算到
            //(這裏的父親是名義上的父親,對於選擇不一樣結點作根,父親與兒子的分佈是不一樣的 
            {
                q.push(lch[node]);
                vis[lch[node]] = 1;
                dis[i][lch[node]] = dis[i][node] + 1;
            }
            if (rch[node] && !vis[rch[node]])
            {
                q.push(rch[node]);
                vis[rch[node]] = 1;
                dis[i][rch[node]] = dis[i][node] + 1;
            }
            if (fa[node] && !vis[fa[node]])
            {
                q.push(fa[node]);
                vis[fa[node]] = 1;
                dis[i][fa[node]] = dis[i][node] + 1;
            }
        }
    }
    int ans, ansv = INT_MAX;
    for (int i = 1; i <= n; i++)
    {
        int nowans = 0;
        for (int j = 1; j <= n; j++)
        {
            nowans += dis[i][j] * sum[j];
        }
        if (nowans < ansv)
        {
            ansv = nowans;
            ans = i;//好像沒有用 
        }
    }
    cout << ansv << endl;
}

跑去luogu上學習了一下O(n)的算法

 大概是沒看懂(微笑狗)

end-

相關文章
相關標籤/搜索