P4934 禮物---------------拓撲圖,優化建邊。
阿新 • • 發佈:2018-10-31
題目描述
__stdcall決定給你nn個禮物,每個禮物有一個魔力值a_iai。這些禮物的魔力值都是獨一無二的,兩兩互不相同。這些禮物都有著神奇的魔力,如果兩個禮物i, ji,j的魔力值滿足 a_i \& a_j \ge min(a_i, a_j)ai&aj≥min(ai,aj) ,那麼這兩個禮物的魔力將會相互抵消,因此它們不能放在一個箱子裡。這裡的\&&是按位與運算子,如果你對這一運算不夠了解,請參考:https://baike.baidu.com/item/%E6%8C%89%E4%BD%8D%E4%B8%8E/9601818?fr=aladdin
作為發禮物苦力的ljt12138的箱子並不多,不過幸運的是,每個箱子都足夠大。現在他請求你幫助他合理分配,用盡可能少的箱子裝下所有禮物。換言之,使得每個禮物都被恰好裝入一個箱子中,且同一個箱子中的禮物魔力不會相互抵消。如果有多種合法的方案,你只需要給出任意一種。
ljt12138十分善良,如果你只能求出所需要的箱子數,也可以獲得該測試點60%的分數,關於這一點,請參考下面的提示與說明。
輸入輸出格式
輸入格式:
-
第一行兩個數 nn和kk,nn為禮物總數,kk為一個引數,方便你進行計算。
-
第二行 nn個兩兩不同的數a_iai,滿足0\le a_i < 2^k0≤ai<2k,表示禮物的魔力值。
輸出格式:
-
第一行輸出一個數。如果你不希望輸出方案,請輸出0;如果你希望輸出方案,請輸出1。如果你在這一行輸出了不符合要求的資訊,將被判為 WAWA。
-
第二行一個數 mm,表示你將禮物裝到了mm個箱子裡。
-
如果你在第一行輸出了 11,接下來mm行,每行表示一個箱子:首先一個數s_isi,表示當前箱子中禮物的個數;接下來s_isi個數,表示當前子集。
輸入輸出樣例
輸入樣例#1:輸出樣例#1:5 3 0 4 7 1 6
1 4 1 0 2 1 4 1 6 1 7
說明
附加樣例:
你可以在 https://pan.baidu.com/s/1A8_ZA4yXXi5y6771x9JKUw 下載附加樣例。
關於輸出方案:
-
如果你在第一行輸出了 00,而正確回答了最小所需的箱子數,將獲得測試點60%的分數。
-
如果你在第一行輸出了 11,正確回答了最小所需的箱子數,但沒有給出正確的方案,也將獲得該測試點60%的分數。
-
如果你沒有正確回答最小所需的箱子數,將不會獲得該測試點的分數。
-
請選手注意,如果你未按照上述格式輸出答案,將無法獲得任何分數。
資料n, kn,k的關係由下面的表格給出:
資料編號 | nn | kk |
---|---|---|
11 | 55 | 33 |
22 | 66 | 33 |
33 | 77 | 1010 |
44 | 88 | 1010 |
55 | 1616 | 77 |
66 | 1717 | 88 |
77 | 1717 | 99 |
88 | 1717 | 2020 |
99 | 20002000 | 1717 |
1010 | 25002500 | 1818 |
1111 | 30003000 | 1919 |
1212 | 30003000 | 2020 |
1313 | 2500025000 | 1515 |
1414 | 2500025000 | 1515 |
1515 | 5000050000 | 1616 |
1616 | 5000050000 | 1616 |
1717 | 250000250000 | 1818 |
1818 | 500000500000 | 1919 |
1919 | 10000001000000 | 2020 |
2020 | 10000001000000 | 2020 |
一句話題解:偏序集最小反鏈覆蓋等於最長鏈,優化建圖。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int siz=2000050; 4 int n,m,a[siz],t; 5 int dis[siz]; 6 bool vis[siz]; 7 int head[siz],nex[siz],tot[siz]; 8 vector <int > s[20]; 9 void add(int x,int y) 10 { 11 ++tot[x]; 12 nex[y]=head[x]; 13 head[x]=y; 14 } 15 int main() 16 { 17 scanf("%d%d",&n,&m); 18 t=(1<<m)-1; 19 for(int i=0;i<n;++i) 20 { 21 scanf("%d",&a[i]); 22 vis[a[i]]=true; 23 } 24 for(int i=t;i>=0;--i) 25 { 26 if(vis[i]) 27 ++dis[i]; 28 for(int j=1;j<t;j<<=1) 29 if(i&j) 30 dis[i^j]=max(dis[i^j],dis[i]); 31 } 32 for(int i=0;i<=t;++i) 33 if(vis[i]) 34 s[dis[i]].push_back(i); 35 printf("%d\n%d",1,dis[0]); 36 for(int i=dis[0];i>=1;--i) 37 { 38 int tmp=s[i].size(); 39 printf("\n%d",tmp); 40 for(int j=0;j<tmp;++j) 41 printf(" %d",s[i][j]); 42 43 } 44 return 0; 45 }程式碼