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

 

posted @ 2018-06-03 11:15  shuai_hui  阅读(153)  评论(0编辑  收藏  举报