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;
}

原文地址:https://www.cnblogs.com/shuaihui520/p/9128514.html

时间: 2024-08-29 23:15:26

CF D. Fair(思维+DFS)的相关文章

HDU 6228 Tree(思维 DFS)

Consider a un-rooted tree T which is not the biological significance of tree or plant, but a tree as an undirected graph in graph theory with n nodes, labelled from 1 to n. If you cannot understand the concept of a tree here, please omit this problem

【2018 ICPC亚洲区域赛沈阳站 L】Tree(思维+dfs)

Problem Description Consider a un-rooted tree T which is not the biological significance of tree or plant, but a tree as an undirected graph in graph theory with n nodes, labelled from 1 to n. If you cannot understand the concept of a tree here, plea

CF 986A Fair——多源bfs

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

Codeforces 510B Fox And Two Dots 【DFS】

好久好久,都没有写过搜索了,看了下最近在CF上有一道DFS水题 = = 数据量很小,爆搜一下也可以过 额外注意的就是防止往回搜索需要做一个判断. Source code: //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <bits/stdc++.h> #define Max(a,b) (((a) > (b)) ? (a) : (b)) #define Min(a,b) (

Leetcode 17 Letter Combinations of a Phone Number - DFS思想

Given a digit string, return all possible letter combinations that the number could represent. A mapping of digit to letters (just like on the telephone buttons) is given below. Input:Digit string "23" Output: ["ad", "ae", &q

cf1061D 贪心+multiset 好题!

cf上的思维题真好! 本题是在模拟的基础上贪心即可:将n段时间按照左端点(右端点为第二关键字)从小到大排序,然后遍历每一个时间段. 对于每一个时间段[li,ri],先找到multiset中最靠近li但在li左侧的r, 如果没有这样的r,即[li,ri]是当前最靠左的,那就需要新加一台电视机,然后把ri加入multiset 如果找到这样的r,那就进行一次判断,如果从r到li等待时间中浪费的钱大于等于新加一台电视的钱,那就新加一台电视,把ri加入multiset 否则就接着r往下看,那就把r从mul

hdu6035[dfs+思维] 2017多校1

/*hdu6035[dfs+思维] 2017多校1*/ //合并色块, 妙啊妙啊 #include<bits/stdc++.h> using namespace std; const double eps=1e-8; const int inf=0x3f3f3f3f; typedef long long LL; vector<int>G[200005]; LL sum[200005]; int c[200005],son[200005],mark[200005]; int n,u,

CF 452B 4-point polyline(思维)

4-point polyline 大意:给你一个网格,从(0, 0)到(n, m).在网格中选出4个不相同的点,按序相连成3段,求3段想加之和最长的情况是什么,输出这种情况. 思路:当时做的时候各种蛋疼,主要是没想对方向,导致一直WA在第3组.今天看到了一个比较清晰的思路. 首先,确定一个短边,我取了m为较短边. 然后情况主要是分3种: 1.当短边为0的情况: 2.计算dis1 3.计算dis2 4.选出(2)跟(3)中距离之和较大的,输出四个点的顺序. 1 /*****************

CF 729D 模拟,思维

CF 729 D. Sea Battle 题意:n个单位长的海域,有a只船,船长为b.已经开了k枪没有射中,求最少再开几枪可射中一只船. 题解:转变一下思维,求开了k枪后可放入多少只船.要求再开几枪可射中一只船,只要 -a+1即可. #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define FF(i,a,b) for (