【反向多源点同时BFS一个强连通图+类最短路题面】Fair-986C-Codeforce

借鉴博客:https://www.cnblogs.com/zhangjiuding/p/9112273.html

 

986-A. Fair

/* 986-A-Fair,codeforce;
大致题意:
      n个点,m个双向边; 一共K中食品,每个点只能提供1种;至少携带s种不同的食品,点u->v 需要花费d(u,v);d(u,v)是最短路u->v,的开销——开销等于该最短路的路径中的边数。每个点有一种食品,食品总的种类数不超过K个,求从每个点出发找至少种食品的最小开销。题目看着像是最短路,起个名字叫做类最短路题目!
大致思路:
      直接进行裸的bfs,我的第一次的做法是枚举每个点作为单源点进行bfs的,这样时间复杂度最大为:(10^5)*(10^5)=顶点数*边数!尽管k只有100个,按理说找100个点不就够了-但可能出现极端情况,比如某几个点特别离散——很偏僻需要搜完整个图才可以找到,这样整个图的复杂度就上升很多了!
     怎么解决呢?再次审题找到突破口,k=100,然后就需要从突破口开始这k种食品的地方进行bfs,每次bfs某一种型号的食品——将该种型号食品的产地作为bfs的起点——更省时!复杂度为k*(10^5)=k *顶点数,及从每种食品开始bfs搜索完整个图存进d[][]中!
*/
 1 #define N 100008
 2 int a[N];
 3 vector<int>G[N];
 4 int d[N][108];//更新每个小镇到第i种食物的最小距离
 5 
 6 void init(int n){
 7     for(int i=0;i<=n;i++)
 8         G[i].resize(0);
 9 }
10 bool vis[N];
11 
12 bool used[N];
13 void bfs(int k,int n){
14         queue<int>Q;
15         for(int i=1;i<=k;i++){//暴力枚举第i种物品的源点,从每种物品的源点开始进行bfs!更省时!
16             memset(used,false,sizeof(used));
17             for(int j=1;j<=n;j++){
18                 if(a[j]==i){
19                     d[j][i]=0;
20                     Q.push(j);
21                     used[j]=true;
22                 }
23             }
24             while(Q.size()>0){//进行BFS!
25                 int x=Q.front();
26                 Q.pop();
27                 for(int t=0;t<(int)G[x].size();t++){
28                     int v=G[x][t];
29                     if(!used[v]){
30                         d[v][i]=d[x][i]+1;//bfs记录节点
31                         used[v]=true;
32                         Q.push(v);
33                     }
34                 }
35             }
36         }
37 }
38 
39 int main(){
40     int n,m,k,s;
41 
42     while(scanf("%d%d%d%d",&n,&m,&k,&s)!=EOF){
43         init(n);
44         for(int i=1;i<=n;i++)
45             scanf("%d",&a[i]);
46         int x,y;
47         for(int i=1;i<=m;i++){
48             scanf("%d%d",&x,&y);
49             G[x].push_back(y);
50             G[y].push_back(x);
51         }
52         bfs(k,n);
53 
54        for(int i=1;i<=n;i++){
55             sort(d[i]+1,d[i]+1+k);
56             int ans=0;
57             for(int j=1;j<=s;j++){
58                 ans+=d[i][j];
59             }
60             printf("%d ",ans);
61        }
62        cout<<endl;
63     }
64     return 0;
65 }

 

 
posted @ 2018-06-01 16:48  山枫叶纷飞  阅读(340)  评论(0编辑  收藏  举报