【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-

相关文章
相关标签/搜索