传送门:点击打开链接
题意: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; }