VIJOS 1321 魔塔

题意

在魔塔中有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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值