一个题目数据小就是那个题目的突破点(一般),比如这个题目,大家貌似都能想到n^2的,但是大家看一眼k的大小会发现,这题的突破点在k(这题不是水题= - =).考虑对于没种颜色做一次bfs,算出其他点到这种颜色的最短距离.
代码如下:
#include <bits/stdc++.h> using namespace std; const int N=1e5+5,M=105; int w[N],ans[N]; vector<int>v[N]; int dis[N][M]; vector<int>col[M]; int vis[N]; queue<int>q; void bfs(int x) { while(q.size()) { int temp=q.front(); q.pop(); for(int i=0;i<v[temp].size();i++) { int pos=v[temp][i]; if(vis[pos]) continue; q.push(pos); dis[pos][x]+=dis[temp][x]+1; vis[pos]=1; } } } int main() { int n,m,k,s; //memset(dis,-1,sizeof dis); scanf("%d%d%d%d",&n,&m,&k,&s); for(int i=1;i<=n;i++) { scanf("%d",&w[i]);//输入每个点的颜色. col[w[i]].push_back(i); } while(m--) { int x,y; scanf("%d%d",&x,&y); v[x].push_back(y); v[y].push_back(x); } for(int i=1;i<=k;i++) { memset(vis,0,sizeof vis); for(int j=0;j<col[i].size();j++) { q.push(col[i][j]); vis[col[i][j]]=1; dis[col[i][j]][i]=0; } bfs(i); } for(int i=1;i<=n;i++) { sort(dis[i]+1,dis[i]+1+k); for(int j=1;j<=s;j++) { // if(i==1) cout<<dis[i][j]<<' '; ans[i]+=dis[i][j]; } }//cout<<endl; for(int i=1;i<=n;i++) printf("%d ",ans[i]); printf("\n"); return 0; }