CodeForces - 986A Fair (BFS+贪心)

题意:有N个点M条边的无向图,每个点有给定的ai(1<=ai<=K,K<=200)表示该点拥有的物品编号,保证1-K在N个点全部出现。求每个点收集S个不同的物品所要走过的最短路程(边的长度为1)。

分析:N是1e5,如果直接对每个点搜索肯定超时。发现K的范围很小,而且1-K全部覆盖。那么考虑对所有1-K的值BFS,用一个二维数组dp[i][j]记录i点要获取编号为j的物品最少走过的路程,并对每个点取最小的S个物品对应的路径。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn =1e5+5;
int a[maxn];
int res[maxn];
vector<int> G[maxn];
bool vis[maxn];
int d[maxn][305];
void init(int N)    {for(int i=1;i<=N;++i) G[i].clear();}
void AddEdge(int u,int v){G[u].push_back(v);}

void BFS(int val,int N)
{
    memset(vis,0,sizeof(vis));
    queue<int> Q;
    for(int i=1;i<=N;++i){
        if(a[i]==val){
            vis[i]=true;
            Q.push(i);
        }
    }
    while(!Q.empty()){
        int x =Q.front();Q.pop();
        for(int i=0;i<G[x].size();++i){
            int v = G[x][i];
            if(!vis[v]){
                vis[v] = true;
                d[v][val] = d[x][val]+1;
                Q.push(v);
            }
        }
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    int N,M,K,S,u,v;
    while(scanf("%d%d%d%d",&N,&M,&K,&S)==4){
        init(N);
        memset(d,0,sizeof(d));
        for(int i=1;i<=N;++i) scanf("%d",&a[i]);
        for(int i=1;i<=M;++i){
            scanf("%d%d",&u,&v);
            AddEdge(u,v);
            AddEdge(v,u);
        }
        for(int i=1;i<=K;++i){
            memset(vis,0,sizeof(vis));
            BFS(i,N);
        }
        for(int i=1;i<=N;++i){
            sort(d[i]+1,d[i]+K+1);
            res[i]=0;
            for(int j =1;j<=S;++j){
                res[i]+=d[i][j];
            }
        }
        for(int i=1;i<N;++i) printf("%d ",res[i]);
        printf("%d\n",res[N]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/xiuwenli/p/9380154.html

时间: 2024-08-30 12:28:03

CodeForces - 986A Fair (BFS+贪心)的相关文章

UVA 12130 - Summits(BFS+贪心)

UVA 12130 - Summits 题目链接 题意:给定一个h * w的图,每个位置有一个值,现在要求出这个图上的峰顶有多少个.峰顶是这样定义的,有一个d值,如果一个位置是峰顶,那么它不能走到不大于该峰顶高度 - d的位置,如果满足这个条件下,并且无法走到更高的山峰,那么它就是峰顶 思路:利用贪心的策略,把所有点丢到优先队列,每次取出最高的峰值开始找,进行广搜,搜的过程中记录下最大值的点的个数,如果这个是峰顶,就加上这个数.判断是不是峰顶的方法为,如果广搜过程中,不会找到一个点的能到的最高峰

Codeforces Round #300——C贪心——Tourist&#39;s Notes

Description A tourist hiked along the mountain range. The hike lasted for n days, during each day the tourist noted height above the sea level. On the i-th day height was equal to some integer hi. The tourist pick smooth enough route for his hike, me

Codeforces 77C 树形dp + 贪心

题目链接:点击打开链接 题意: 给定n个点, 每个点的豆子数量 下面是一棵树 再给出起点 每走到一个点,就会把那个点的豆子吃掉一颗. 问:回到起点最多能吃掉多少颗豆子 思路:树形dp 对于当前节点u,先把子节点v都走一次. 然后再往返于(u,v) 之间,直到u点没有豆子或者v点没有豆子. dp[u] 表示u点的最大值.a[u] 是u点剩下的豆子数. #include <cstdio> #include <vector> #include <algorithm> #inc

UVA12130 Summits(BFS + 贪心)

UVA12130 Summits(BFS + 贪心) 题目链接 题目大意: 给你一个h ? w 的矩阵,矩阵的每个元素都有一个值,代表这个位置的高度.题目要求你找出这个图中有多少个位置是峰值点.从每个点(高度H)出发遍历这个图有一个要求,就是走过的点的高度不能小于等于H - d:成为峰值点的要求就是从这个点出发走到的位置不能有高度大于H的. 解题思路: 因为图很大,用dfs肯定不行.将这些点按照高度从大到小的排序,然后每个点作为起点来遍历,如果找到比这个点大的点就说明不是峰值点.并且遍历的过程中

CF 986A Fair——多源bfs

题目:http://codeforces.com/contest/986/problem/A 此题乍一看没什么不T的思路... 发现边权是1,bfs? 考虑朴素的想法,遍历所有的点,bfs,过程中更新出各种商品的最短路,然后排序加和-- 好像很不行,似乎有一大堆冗余的东西,主要因为每个点上只有一种商品啊: 不妨干脆换个思路,不是找每个点到每种商品的距离,而是找每种商品到每个点的距离,如何? 一种商品存在于多个点上,可以进行多源 bfs! 也就是 bfs 一开始的时候把多个点加进优先队列里,复杂度

Codeforces 788A Functions again - 贪心

Something happened in Uzhlyandia again... There are riots on the streets... Famous Uzhlyandian superheroes Shean the Sheep and Stas the Giraffe were called in order to save the situation. Upon the arriving, they found that citizens are worried about

luogu 1066 引水入城(bfs+贪心)

90分,有一个点TLE.... 首先可以证明一个东西,如果从上面一排的某个点bfs一次到最下面一排的饮水点不是一个区间的话,那么最后一定所有饮水点不会被覆盖完的. 证明考虑反证法. 所以从上面一排的每个点bfs一次得到一个区间.题目转化为给出m个区间覆盖m个点的最小区间选择数. 显然是个明显的贪心,以左区间端点为第一关键字升序排序,右区间端点为第二关键字降序排序,那么每次贪心的选择一个覆盖最大的区间即可. 时间复杂度O(n*m^2+mlogm).需要常数优化. # include <cstdio

Codeforces 486C Palindrome Transformation(贪心)

题目链接:Codeforces 486C Palindrome Transformation 题目大意:给定一个字符串,长度N,指针位置P,问说最少花多少步将字符串变成回文串. 解题思路:其实只要是对称位置不相同的,那么指针肯定要先移动到这里,修改字符只需要考虑两种方向哪种更优即 可.然后将所有需要到达的位置跳出来,贪心处理. #include <cstdio> #include <cstring> #include <cstdlib> #include <vec

codeforces 735C Tennis Championship(贪心+递推)

Tennis Championship 题目链接:http://codeforces.com/problemset/problem/735/C --每天在线,欢迎留言谈论. 题目大意: 给你一个 n (2≤n≤10^18),代表一共有n位参加比赛的选手. 游戏规则: ①每次比赛,输的选手将离开赛场 ②相互比赛的选手 他们的获胜的次数相差不能超过1(获胜4次的选手只能跟3或5次的选手比赛) 问题:最终赢得比赛的选手,胜场最多能为多少. 思路: 贪心:①选一名选手让他一直获胜且优先让他参加比赛 ②当