nowcoder 常州大学 新生 I





/*
链接:https://www.nowcoder.com/acm/contest/78/I
来源:牛客网

题目描述 
有机合成是指从较简单的化合物或单质经化学反应合成有机物的过程。
有时也包括从复杂原料降解为较简单化合物的过程。
由于有机化合物的各种特点,尤其是碳与碳之间以共价键相连,有机合成比较困难,常常要用加热、光照、加催化剂、加有机溶剂甚至加压等反应条件。
但是前人为有机合成提供了许多宝贵的经验。
现在已知有K总物质和N个前人已经总结出的合成反应方程式
小星想知道在现有M种物质的情况下 能否合成某些物质。
输入描述:
第一行输入四个整数 K,N,M,Q(K,N,M,Q<=1e5)
K表示一共K总物质
接下来N行 每行三个数字a b c(任意两个数可能相等)
表示a和b反应可以生成c 反应是可逆的
即可以通过c可以分解出a和b
接下来一行行然后输入m个数,表示m种原料(每一种原料都可以认为有无限多)
接下来Q个行Q个询问
对于每个询问
输出一个数字 x 判断是否可以通过一些反应得到第 x
输出描述:
可以得到Yes否则No
示例1
输入
10 3 4 10
1 2 3
4 5 6
2 5 7
3 4 5 8
1
2
3
4
5
6
7
8
9
10
输出
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
No
No
说明
一共10总物质有第3,4,5,8 四种原料
查询每一种是否可以通过反应得到
首先通过3可以分解得到1 2
然后4 5合成6
2 5合成7
于是除了9 10都可以得到
*/

#include<bits/stdc++.h>
using namespace std;
#define maxn 100000+100
bool flag[maxn];
vector<int>w[maxn];
/*struct ac{
   int x,y,z;
   ac(){};
   ac(int a,int b,int c){
     x=a;
     y=b;
     z=c;
   }
}a[maxn];*/
//vector<pair<int,int> >w;
bool xxx(int x){
   for(int j=0;j<w[x].size();j+=2){
      int xx=w[x][j];
      int yy=w[x][j+1];
      if(flag[xx]&&flag[yy]){
         return true;
      }
   }
   return false;
}
int main(){
   int k,n,m,q;
   cin>>k>>n>>m>>q;
   for(int j=0;j<n;j++){
      int x,y,z;
      scanf("%d%d%d",&x,&y,&z);
      w[0].push_back(z);
      w[z].push_back(x);
      w[z].push_back(y);
      //a[z].x=x;
      //a[z].y=y;
   }
  // memset(flag,0,sizeof(flag));
   for(int j=0;j<m;j++){
      int x;
      scanf("%d",&x);
      flag[x]=1;
   }
   int ans=0;
   int len1=w[0].size();
   while(ans<=sqrt(k)){
       for(int j=0;j<len1;j++){ //被合成的所有集合
          int x=w[0][j];
          if(flag[x]){        //已经被合成 把他的儿子全部标记为合成
             for(int kk=0;kk<w[x].size();kk++){
                int y=w[x][kk];
                flag[y]=1;
             }
          }
          if(!flag[x]){      //不能被合成
             bool i=0;
             i=xxx(x);    //判断儿子是否有被合成的
             if(i){
               flag[x]=1;
             }
          }
       }
       ans++;
   }
   for(int j=0;j<q;j++){
     int x;
     scanf("%d",&x);
     printf(flag[x]? "Yes\n":"No\n");
   }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值