VIJOS 1321 魔塔

来源:互联网 发布:办公平台软件 编辑:程序博客网 时间:2024/05/19 23:10

题意

在魔塔中有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;}
0 0
原创粉丝点击