传送门:点击打开链接
题意:n个城市,m条无向路,共有k种货物,每个城市只有一种货物,让你求在城市i举办交易会,至少有s种货物参加,求最少的路径之和
分析:两种思路,一是直接对每一个进行点bfs,找到s种不同货物直接返回,复杂度大约为O(n*s)(标记的时候要用bool类型的数组,用int型会超时),二是进行k遍bfs,暴力k种颜色到每个点的最短距离,最后对这k种颜色到每个点的距离排序取前s个做和。
代码一:
///思路一
#include<bits/stdc++.h>
using namespace std ;
const int N = 1e5+10 ;
typedef long long ll;
vector<int> mp[N];
int a[N],d[N],n,m,k,s;
bool vis[N],ct[N];
///标记数组一定要用bool类型节约时间,否则会tle
void bfs(int x)
{
memset(vis,0,sizeof(vis));
memset(d,0,sizeof(d));
memset(ct,0,sizeof(ct));
vis[x]=1;
ct[a[x]]=1;
queue<int> q;
q.push(x);
int sum=1,ans=0;
d[x]=0;
if(s==1) {
if(x==n) cout<<0<<endl;
else cout<<0<<" ";
return ;
}
while(!q.empty())
{
int tp=q.front();
q.pop();
for(int i=0; i<mp[tp].size(); i++)
{
int u=mp[tp][i];
if(!ct[a[u]])
{
q.push(u);
sum++;
vis[u]=1;
d[u]=d[tp]+1;
ans += d[u];
if(sum==s)
{
cout<<ans;
if(x==n) cout<<endl;
else cout<<" ";
return ;
}
}
}
for(int i=0; i<mp[tp].size(); i++)
{
int u=mp[tp][i];
if(!vis[u])
{
vis[u]=1;
q.push(u);
d[u]=d[tp]+1;
}
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin>>n>>m>>k>>s;
for(int i=1; i<=n; i++)
cin>>a[i];
for(int i=0; i<m; i++)
{
int x,y;
cin>>x>>y;
mp[x].push_back(y);
mp[y].push_back(x);
}
for(int i=1; i<=n; i++)
bfs(i);
return 0 ;
}
代码二:
///思路二
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
#define pb push_back
int d[N][105],v[N],n,m,k,s,ans[N];
vector<int> e[N];
void bfs(int x) {
queue<int> q;
for(int i=1;i<=n;i++) {
if(v[i]==x) {
d[i][x]=0;
q.push(i);
}
}
int tp;
while(!q.empty()) {
tp = q.front();q.pop();
for(int i=0;i<e[tp].size();i++) {
int u=e[tp][i];
if(d[u][x]==-1) {
d[u][x]=d[tp][x]+1;
q.push(u);
}
}
}
}
int main() {
ios::sync_with_stdio(0);
cin>>n>>m>>k>>s;
for(int i=1;i<=n;i++)
cin>>v[i];
for(int i=1;i<=m;i++) {
int v1,v2;
cin>>v1>>v2;
e[v1].pb(v2);
e[v2].pb(v1);
}
for(int i=1;i<=k;i++) {
for(int j=1;j<=n;j++)
d[j][i]=-1;
bfs(i);
}
for(int i=1;i<=n;i++) {
sort(d[i]+1,d[i]+k+1);
int sum=0;
for(int j=1;j<=s;j++)
sum+=d[i][j];
ans[i]=sum;
}
for(int i=1;i<n;i++)
cout<<ans[i]<<" ";
cout<<ans[n];
return 0;
}