CF D. Fair(思维+DFS)
http://codeforces.com/contest/987/problem/D
题目大概:
给出一个n个城镇m条边的图,给出每个城镇拥有的特产(可能多个城镇有相同特产)。有k种不同特产。
要求每个城镇需要其他城镇运输特产到自己的城镇,每个城镇必须拥有s种特产,那么在城镇满足s种特产后,需要的最短路径是多长,最短路指的是特产运输过来走过的边的数量。
分析:
一开始以为是道水题,因为我只要对每个点都进行一次DFS,那问题就很简单了,但是。。。细想下,这其实是不行的,因为会TLE. 那现在我们来转化下思维,城市太多了,可是特产的种类很少,所以!!!!我们算出每种特产到每个城市的最短距离,然后把所有到i城镇的特产的最短路 排序,取前s个就是i点的最短路径了。
#include <bits/stdc++.h> using namespace std; const int maxn=1e5+5; const int INF=0x3f3f3f3f; int e[maxn]; int vis[maxn];///标记 int lis[maxn][120];///记录 vector<int>F[120];///每种特产到每个城市 vector<int>G[maxn];///建图 struct poin { int x,d; }; int ans=0; int s; void bfs(int x) { queue<poin>Q; ///x种特产的开始城市 for(int i=0;i<F[x].size();i++) { int v=F[x][i]; poin q; q.x=v;q.d=0; Q.push(q); } ///x种特产去到的城市 while(!Q.empty()) { poin u=Q.front();Q.pop(); ///u.x城市到x特产的最短距离 lis[u.x][x]=min(u.d,lis[u.x][x]); for(int i=0;i<G[u.x].size();i++) { int v=G[u.x][i]; if(vis[v])continue; vis[v]=1; poin q; q.x=v; q.d=u.d+1; Q.push(q); } } } int main() { int n,m,k; scanf("%d%d%d%d",&n,&m,&k,&s); for(int i=1;i<=n;i++) { scanf("%d",&e[i]); F[e[i]].push_back(i);///e[i]产品在多少城市 } int u,v; for(int i=1;i<=m;i++) { scanf("%d%d",&u,&v); G[u].push_back(v);///无向图 G[v].push_back(u); } memset(lis,0x3f3f3f3f,sizeof(lis)); for(int i=1;i<=k;i++) { memset(vis,0,sizeof(vis)); bfs(i);///对每种特产DFS } for(int i=1;i<=n;i++) { sort(lis[i]+1,lis[i]+k+1);///排序 long long sum=0; ///i城市拥有的s种特产的最短距离 for(int j=1;j<=s;j++) { sum+=lis[i][j]; } printf("%I64d ",sum); } return 0; }