题意
在魔塔中有N个房间和M条道路,每条道路上有一个怪,它可以被一种特殊的武器消灭,而每个房间中也存在一种武器。现在知道第I个房间中的武器编号为I,小明(主人翁)初始在J房间,小明想知道哪些房间是他可以去的。
数据范围 1<=m<=50000,1<=a,b,J<=n<=50000
提示:m,n<50000不等于说数组可以只开到50000;输出前面无空格
分析
显然,一个房间在一个时刻能抵达,那么以后也可以
一个房间能被访问的条件是:1有相邻房间被访问 2相邻房间连着的道路可以通过
我们每访问一个房间i,都能使得一些新房间的条件得到满足,这些新房间就可能可以被访问
因此,我们在访问完房间i后
将i连向的房间检查一次能否访问
将怪物i守住的道路检查一次能否访问
这样就能保证每条路和每个节点都只被访问一次了
时间复杂度O(n+m)
代码
#include<cstdio>
#define fo(i,a,b) for(int i=a;i<=b;i++)
const int mn=50000+100,mm=50000+100;
int n,s,m,aa,bb,cc,be[mn],bc[mn],et,ct;
bool p[mn];
struct edge{
int y,z,ne;
};
edge e[mm*2],c[mm];
void add_edge(int u,int v,int w){
e[++et].y=v;
e[et].z=w;
e[et].ne=be[u];
be[u]=et;
}
void add_edge2(int u,int v,int w){
c[++ct].y=v;
c[ct].z=w;
c[ct].ne=bc[u];
bc[u]=ct;
}
void dfs(int x){
p[x]=1;
int i=bc[x];
while (i){
int &y=c[i].y,&z=c[i].z;
if (p[y]&&(!p[z]))
dfs(z);
if (p[z]&&(!p[y]))
dfs(y);
i=c[i].ne;
}
i=be[x];
while (i){
int &y=e[i].y,&z=e[i].z;//int &y=c[i].y,&z=c[i].z;
if (p[z]&&(!p[y]))
dfs(y);
i=e[i].ne;
}
}
int main(){
scanf("%d%d%d",&n,&s,&m);
fo(i,1,m){
scanf("%d%d%d",&aa,&bb,&cc);
add_edge(aa,bb,cc);
add_edge(bb,aa,cc);
add_edge2(cc,aa,bb);
}
dfs(s);
fo(i,1,n){
printf("%d:",i);
if (p[i])
printf("Yes\n");
else
printf("No\n");
}
return 0;
}