【模拟赛·食物中毒】

背景

WZOI的小组成员今天集体食物中毒,什么事情也不能干了,这是一件十分可怕的事。幸亏WZOI的Bqc同志十分在行化学,他可以马上制作出解药来……

问题描述

Bqc经过一段时间的研究发现,要解这种毒需要一种特殊的药物。不幸的是,这种药物在市面上不存在,没有办法Bqc只好亲自制得这种药物。它含有M种化学物质A1,A2,…,AM。现在Bqc的手上有N种药材(每种药材只有一种),每种药材含有若干种化学物质(Bqc他有一种机器,只要将药材放入机器,就能制得相应的药物)。 Bqc需要你的帮助,他希望你能帮他选取若干种药材,用这些选取的药材制作出Bqc需要的药物。由于这些化学物质是有毒的,因此你选出来的药物,必须含有这M种化学物质。有一点需要注意:根据中医以毒攻毒的理论,两个相同的化学物质在一起,它们的药性会同时消失变为一种无毒物质(大多情况下这种无毒物质会挥发掉,也就是说这种化学物质消失了)。比如说药材1有化学物质1、2,药材2有化学物质1、3,那么如果药材1和药材2混合,你得到的药物会含有化学物质2、3。 Bqc问你,需要选用那些药材可以制得他想要的药物?

输入格式

本题每个测试点存在多组数据,每组输入数据第1行包含两个整数N和M,表示Bqc拥有的药材数目和他所需药物所含的化学物质的种类数目; 第2行共有M个整数,分别表示M中化学物质的编号,用1~50之间的数字编号(输入数据保证同一种化学物质不会被描述多次); 第3行到第N+2行,每行包含若干个数。第i+2行的第一个数为Mi,表示药材i包含Mi中化学物质,接下来Mi个数,描述药材i含有的化学物质的编号,用1~50之间的数字编号(同一种化学物质可能会被描述多次)。 每组输入数据用一个空行隔开。输出格式对于每组数据输出一行,如果用这些药材可以制得Bqc需要的药物,那么输出“Possible”;否则输出“Impossible”,不包含引号。

样例输入

输出

medicine.in

medicine.out

2 2 2 3 2 1 5 2 1 3 3 3 1 3 4 4 2 3 4 1 1 4

Impossible

Possible

Possible

3 样例解释对于样例的第三组数据,可行的方案有选取 1、3 和选取 2、4. 数据规模对于30%的数据,N≤10,M≤20;对于50%的数据,N≤20,M≤40;对于100%的数据,N≤20,M≤50;对于100%的数据,Mi≤50。保证测试数据的组数不超过100。时间限制 1s 提示同一种化学物质被描述偶数次,那么说明这种物质不存在;否则这种物质存在。

【题解】

      ①STD:暴搜,时间复杂度由于有T的存在是O(108)左右

      ②我:

              由于只管治病的物质,因此将治病的物质编号压入线性基,

              然后查询能否构造11111……1111就是了。时间复杂度O(5*106)

#include<stdio.h>
#include<cstring>
#include<algorithm>
#define Xor go(j,1,m)x[j]^=A[i][j]
#define go(i,a,b) for(int i=a;i<=b;i++)
int n,m,a[103],M,t,index[103],x[55];bool Prior[103];

struct Linear_Base
{
	int A[55][55],have[55];
	void Clear(){go(i,1,m){have[i]=0;go(j,1,m)A[i][j]=0;}}
	void Insert()
	{
		go(i,1,m)if(x[i]){if(!have[i]){have[i]=1;
		go(j,1,m)A[i][j]=x[j];i=m;}else Xor;}
	}
	bool Capable()
	{
		go(i,1,m)if(x[i]&&A[i][i])Xor;
		int sum=0;go(i,1,m)sum+=x[i];return sum==0;
	}
}Tool;

int main()
{
	freopen("medicine.in","r",stdin);
	freopen("medicine.out","w",stdout);
	
	while(~scanf("%d%d",&n,&m))
	{
		Tool.Clear();
		memset(Prior,0,sizeof(Prior));
		go(i,1,m)scanf("%d",a+i),Prior[a[i]]=1;
		std::sort(a+1,a+m+1);go(i,1,m)index[a[i]]=i;
		go(i,1,n){scanf("%d",&M);memset(x,0,sizeof(x));
		go(i,1,M){scanf("%d",&t);if(Prior[t])x[index[t]]^=1;}
		Tool.Insert();}go(i,1,m)x[i]=1;puts(Tool.Capable()?"Possible":"Impossible");
	}
	return 0;
}//Paul_Guderian

.

原文地址:https://www.cnblogs.com/Damitu/p/7778139.html