CQOI-1634 外星人入侵

题目

题目描述

外星人入侵地球。可怕的吃人外星人正在全国各地依次序建立它们的基地。
全国共有N(1≤ N ≤10,000)座城市,城市编号1~N。城市之间有M(0≤ M ≤100,000)条双向道路相连。外星人计划建立A(0≤A≤N)个基地。
你只有在距离当前所有外星人基地至少K(1≤K≤100)单位长度的城市才能得到安全。

所以你必须赶快写一个程序决定走到哪里去。

输入

第1行:4个整数N, M, A, K
接下来M行,每行3个整数T1, T2(1≤T1

输出

共A行,第i行1个整数,表示当外星人建好第i个基地后,距离当前所有基地B1,B2,…,Bi至少K长度的城市的数量。

样例输入

7 6 3 3
1 2 1
1 3 1
2 5 1
3 6 1
1 4 1
4 7 2
2
1
4

样例输出

2
1
0

分析

首先我们想,当一个城市被外星人占领之后,我们就应该将与这个城市相隔不超过K的城市全部做上记号(我在这里用的set,存被威胁的所有城市)
那么就用DFS吧,又快,写起来还简单

void Dfs(int x,int val){
    if(val<k) ans.insert(x);
    for(int i=0;i<edge[x].size();i++)//这道题用邻接矩阵是会炸的
        if((val+edge[x][i].first)<k)
            Dfs(edge[x][i].second,val+edge[x][i].first);
}

但是就这样写了过后,却会TLE
TLE截图
原因在哪呢?
当我们访问一个点时,如果这个点已经被访问过了,且前面的人(外星)在到达这个点后能走的路程比当前这个外星人还要长,那这一次的DFS到这里就可以结束了,而不需要再继续往下走。
所以我们加入一个T数组,作用是记录从这个点出发最多能走多远

if(go[x]>=k-val) return;
    else go[x]=k-val;

这样就完成了

代码

#include<set>
#include<cstdio>
#include<vector>
using namespace std;
#define MAXN 10000
int n,m,a,k,go[MAXN+5];
set <int> ans;
vector < pair<int,int> > edge[MAXN+5];
void Dfs(int x,int val){
    if(val<k) ans.insert(x);
    if(go[x]>=k-val) return;
    else go[x]=k-val;
    for(int i=0;i<edge[x].size();i++)
        if((val+edge[x][i].first)<k)
            Dfs(edge[x][i].second,val+edge[x][i].first);
}
int main(){
    //freopen("data.txt","r",stdin);
    scanf("%d %d %d %d",&n,&m,&a,&k);
    for(int i=1;i<=m;i++){
        int op,ed,val;
        scanf("%d %d %d",&op,&ed,&val);
        edge[op].push_back(make_pair(val,ed));
        edge[ed].push_back(make_pair(val,op));
    }
    for(int i=1;i<=a;i++){
        int number;
        scanf("%d",&number);
        Dfs(number,0);
        printf("%d\n",n-ans.size());
    }
    return 0;
}
posted @ 2018-03-26 13:57  SteinGate  阅读(124)  评论(0编辑  收藏  举报