问题描述
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”,不包含引号。
样例输入
2 2
2 3
2 1 5
2 1 3
3 3
1 3 4
4 2 3 4 1
1 4
2 2 1
4 4
1 2 3 4
3 1 3 4
3 1 4 5
1 2
2 2 3
样例输出
Impossible
Possible
Possible
其实吧,这道题我把它画成图,我还以为可以用二分图匹配做,后来发现tan90°,然后就只有用状压了,毕竟这个选到指定种类的题很容易想到用二进制表示状态
然后就是一个暴力搜索了,原本是打着死马当活马医的态度做这题,结果竟然还一次就A了
【思路】
数组f[i]表示第i个数含有哪些物质(二进制表示),然后暴力搜索;
有个叫大米兔的大佬还提出了更强的解法,就是用线性基,优化了很多啊
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #define maxn 55
8 #define ll long long
9 using namespace std;
10
11 ll f[maxn];
12 ll goal,n,m;
13 int vis[maxn],y[maxn],tr=0;
14
15 int read(){
16 int xx=0,ff=1;char ch=getchar();
17 while(ch<'0'||ch>'9'){if(ch=='-')ff=-1;ch=getchar();}
18 while(ch>='0'&&ch<='9'){xx=xx*10+ch-'0';ch=getchar();}
19 return xx*ff;
20 }
21
22 void dfs(int pos,ll now){
23 if(tr==1)return;
24 if(now==goal){printf("Possible\n");tr=1;return ;}
25 if(pos==n+1)return;
26 if(!vis[pos]){
27 vis[pos]=1;dfs(pos+1,now^f[pos]);vis[pos]=0;
28 }
29 if(tr==1)return;
30 dfs(pos+1,now);
31 }
32
33 int main(){
34 freopen("medicine.in","r",stdin);
35 freopen("medicine.out","w",stdout);
36 while(~scanf("%lld%lld",&n,&m)){
37 goal=0;memset(f,0,sizeof(f));tr=0;
38 memset(vis,0,sizeof(vis));
39 memset(y,0,sizeof(y));
40 for(int i=1;i<=m;i++){
41 int a;a=read();y[a]++;
42 goal^=1ll<<(a-1);
43 }
44 for(int i=1;i<=n;i++){
45 int k;k=read();
46 for(int j=1;j<=k;j++){
47 int a;a=read();
48 if(y[a])f[i]^=1ll<<(a-1);
49 }
50 }dfs(1,0);
51 if(!tr)printf("Impossible\n");
52 }
53 }
我dfs打的丑不要笑,主要是习惯了以dep为参数的dfs,这次以pos的还有点不熟悉QAQ