醫院設置【題目連接】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-