zoj 3811 Untrusted Patrol 牡丹江网络赛c题

Untrusted Patrol

Time Limit: 3 Seconds       Memory Limit: 65536 KB

Edward is a rich man. He owns a large factory for health drink production. As a matter of course, there is a large warehouse in the factory.

To ensure the safety of drinks, Edward hired a security man to patrol the warehouse. The warehouse has N piles of drinks and M passageways connected them (warehouse is not big enough). When the evening comes, the security man will start to patrol the warehouse following a path to check all piles of drinks.

Unfortunately, Edward is a suspicious man, so he sets sensors on K piles of the drinks. When the security man comes to check the drinks, the sensor will record a message. Because of the memory limit, the sensors can only record for the first time of the security man's visit.

After a peaceful evening, Edward gathered all messages ordered by recording time. He wants to know whether is possible that the security man has checked all piles of drinks. Can you help him?

The security man may start to patrol at any piles of drinks. It is guaranteed that the sensors work properly. However, Edward thinks the security man may not works as expected. For example, he may digs through walls, climb over piles, use some black magic to teleport to anywhere and so on.

Input

There are multiple test cases. The first line of input is an integer T indicates the number of test cases. For each test case:

The first line contains three integers N (1 <= N <= 100000), M (1 <= M <= 200000) and K (1 <= K <= N).

The next line contains K distinct integers indicating the indexes of piles (1-based) that have sensors installed. The following M lines, each line contains two integers Ai and Bi (1 <= AiBi <=N) which indicates a bidirectional passageway connects piles Ai and Bi.

Then, there is an integer L (1 <= L <= K) indicating the number of messages gathered from all sensors. The next line contains L distinct integers. These are the indexes of piles where the messages came from (each is among the K integers above), ordered by recording time.

Output

For each test case, output "Yes" if the security man worked normally and has checked all piles of drinks, or "No" if not.

Sample Input
2
5 5 3
1 2 4
1 2
2 3
3 1
1 4
4 5
3
4 2 1
5 5 3
1 2 4
1 2
2 3
3 1
1 4
4 5
3
4 1 2
Sample Output
No
Yes
 
 
 
题意是有n个仓库,其中m个装了传感器,可以得到保安到达此仓库的信息,给出了各个仓库之间的连接关系,从一个仓库只能到有路径相连的仓库。
给出传感器记录的顺序,判断保安是否按照所给路径巡逻(即没有跨越两个没有路径相连的仓库)。
这题主要是学到了链式邻接表,比邻接矩阵可以存储更多的点和边。
 
代码:
 
#include<stdio.h>
#include<string.h>
#define N 100005
#define M 400005

int ts[N],vis[N];//ts用来记录此点是否有传感器,vis标记是否访问过此点
int p[M],q[M],next[M],first[M],kk[M];//邻接表的各个数组,p、q表示一个边的两个点,first表示与此点链接的上一条边,next表示与此边相邻的下一条边
int cnt,counts;//记录访问的边数和点数

void dfs(int u)//搜索
{
    int e,v;

    e=first[u];//从给出的u点的第一条边开始搜索
    while(e!=0)
    {
        v=q[e];//第一条边的起点
        //printf("dfs%d\t\t%d\t\n",e,v);
        if(vis[v]==0)
        {
            vis[v]=1;
            if(ts[v]==1)//如果有传感器信息
            {
                cnt++;//边数++
                counts++;//带传感器的点数++
                ts[v]=0;//取消标记传感器
            }
            else
            {
                cnt++;//边数++
                dfs(v);//深度搜索相连的下一条边
            }
        }
        e=next[e];//下一条边
    }
}

int main()
{
    int v,u,i,e,m,T,n,k,l;

    scanf("%d",&T);
    while(T--)
    {
        int x;
        memset(first,0,sizeof(first));
        memset(ts,0,sizeof(ts));
        memset(vis,0,sizeof(vis));
        //memset(next,0,sizeof(next));
        scanf("%d%d%d",&n,&m,&k);
        for(i=0;i<k;i++)
        {
            scanf("%d",&x);
            ts[x]=1;//将带传感器的标记
        }
        for(i=1;i<=m;i++)//构造邻接表,边数为m,则用i和i+m存放相反的两条边,即为没有方向
        {
            scanf("%d%d",&u,&v);
            p[i+m]=q[i]=v;
            q[i+m]=p[i]=u;
            next[i]=first[u];
            first[u]=i;
            next[i+m]=first[v];
            first[v]=i+m;
        }
        scanf("%d",&l);
        for(i=0;i<l;i++)
            scanf("%d",&kk[i]);
        if(l<k)printf("No\n");//记录到达信息不全,肯定是没有全走完
        else
        {
            ts[kk[0]]=0;//把第一个到的有传感器的点搞成0
            vis[kk[0]]=1;
            for(i=0,counts=1,cnt=1;i<l;i++)//从第一个由传感器检测到的点开始搜索
            {
                if(ts[kk[i]]==1)//如果有没搜索到的有传感器的点即跳出
                    break;
                dfs(kk[i]);
            }
            //printf("%d  %d\n",counts,cnt);
            if(counts==l&&cnt==n)//如果搜索的边数==n并且点数等于传感器记录的点数就yes
                printf("Yes\n");
            else printf("No\n");
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值