题目
题目描述
外星人入侵地球。可怕的吃人外星人正在全国各地依次序建立它们的基地。
全国共有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
原因在哪呢?
当我们访问一个点时,如果这个点已经被访问过了,且前面的人(外星)在到达这个点后能走的路程比当前这个外星人还要长,那这一次的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;
}