2019年中南大学机试题D题
题目描述
CSU镇上有n个商店,n个商店有m条双向小路相连,在这n个商店里共有k种不同商品,每个商店只有一种商品,每条路的权重都为1。现问你从每个商店出发,买够k种商品中的s种商品所需的最小代价,每个商店可以同时派出多个人买不同商品,买够即可。
输入
输入包含多组测试用例。
对于每一组输入包含四个数字n ,m, k,s (1<=n<=m<=1e5 , 1<=s<=k<=min(n,100))
分别代表商店数,小路数,商品种数,需要的商品数。
接下来n个数 a1,a2...an (1<=ai<=k),ai代表第i个商店的商品编号。
接下来m行小路(u,v),u≠v,代表商店u和v之间有小路连接。
输出
输出n个数字,第i个数字代表从商店i出发买够s种商品所需的最小代价。
样例输入
5 5 4 3
1 2 4 3 2
1 2
2 3
3 4
4 1
4 5
7 6 3 2
1 2 3 3 2 2 1
1 2
2 3
3 4
2 5
5 6
6 7
样例输出
2 2 2 2 3
1 1 1 2 2 1 1
题目思路
就是道bfs题,但是和一般的BFS不同。这道题要用多源BFS。题目求的是每个商店购买s中物品的代价。每个商店都去求一遍BFS。但是你会发现n太大了。会超时。n>>k的,可以换个思考,对物品进行BFS。就是求每个物品的商店到各个商店的最小步数。比求各个商店到每个物品的商店的步数花费的时间要小的很多。
上代码
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXM = 1e5+5;
int shop[MAXM];
vector<int> goods[MAXM];
int ans[MAXM][200];
void bfs(int index, int n)
{
queue<int> q;
int now;
for(int i = 1; i <= n; i++)
if(shop[i] == index)
{
// 如果该商店的物品就是要搜索的物品则代价为0
ans[i][index] = 0;
// 从拥有该物品的商店开始搜索
q.push(i);
}
while(!q.empty())
{
now = q.front();
for(int i = 0; i < goods[now].size(); i++)
{
// 搜素与该商店有通路的店子
int nex = goods[now][i]; // 现在搜索到的商店编号
if(ans[nex][index] == -1)
{
// 该商店还没被搜索到, 则购买index物品的代价为上一步的代价+1
ans[nex][index] = ans[now][index] + 1;
q.push(nex); // 把此商店加入过搜索队列之中
}
}
q.pop();
}
}
int main()
{
int n, m, k, s, u, v, an;
while(scanf("%d %d %d %d", &n, &m, &k, &s) != EOF)
{
for(int i = 1; i <= n; i++)
{
goods[i].clear();
scanf("%d", &shop[i]);
}
for(int i = 1; i <= m; i++)
{
scanf("%d %d", &u, &v);
//用vector存储每个商店与其他商店的是否有
goods[u].push_back(v);
goods[v].push_back(u);
}
memset(ans, -1, sizeof(ans));
for(int i = 1; i <= k; i++)// 求每个商店购买第i的物品所需要的代价
bfs(i, n);
for(int i = 1; i <= n; i++)
{
an = 0;
// 我们把第i个商店购买各个物品所需要的代价排序
//我们存数据的时候是从1开始的所以要加1
sort(ans[i]+1, ans[i]+1+k);
// 从中挑选代价最小的s个物品
for(int j = 1; j <= s; j++)
an += ans[i][j];
printf("%d ", an);
}
printf("\n");
}
return 0;
}
原文地址:https://www.cnblogs.com/Mrs-Jiangmengxia/p/12641522.html
时间: 2024-10-01 05:10:22