题目:http://codeforces.com/contest/986/problem/A
此题乍一看没什么不T的思路...
发现边权是1,bfs?
考虑朴素的想法,遍历所有的点,bfs,过程中更新出各种商品的最短路,然后排序加和……
好像很不行,似乎有一大堆冗余的东西,主要因为每个点上只有一种商品啊;
不妨干脆换个思路,不是找每个点到每种商品的距离,而是找每种商品到每个点的距离,如何?
一种商品存在于多个点上,可以进行多源 bfs!
也就是 bfs 一开始的时候把多个点加进优先队列里,复杂度 n*k;
所以以后遇到正着做很麻烦问题,不妨反过来考虑一下。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<queue> using namespace std; int const maxn=1e5+5; int n,m,k,s,dis[maxn][105],hd[maxn],ct; vector<int>v[105]; queue<int>q; struct N{ int to,nxt; N(int t=0,int n=0):to(t),nxt(n) {} }ed[maxn<<1]; void add(int x,int y){ed[++ct]=N(y,hd[x]); hd[x]=ct;} int main() { scanf("%d%d%d%d",&n,&m,&k,&s); memset(dis,0x3f,sizeof dis); for(int i=1,x;i<=n;i++) { scanf("%d",&x); dis[i][x]=0; v[x].push_back(i); } for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } for(int i=1;i<=k;i++) { while(q.size())q.pop(); for(int j=0;j<v[i].size();j++)q.push(v[i][j]); while(q.size()) { int x=q.front(); q.pop(); for(int j=hd[x],u;j;j=ed[j].nxt) { if(dis[u=ed[j].to][i]>dis[x][i]+1) dis[u][i]=dis[x][i]+1,q.push(u); } } } for(int i=1;i<=n;i++) { int sum=0; sort(dis[i]+1,dis[i]+k+1); for(int j=1;j<=s;j++)sum+=dis[i][j]; printf("%d ",sum); } return 0; }
原文地址:https://www.cnblogs.com/Zinn/p/9275485.html
时间: 2024-09-29 22:45:14