現在有一種卡牌遊戲,每張卡牌上有三個屬性值:a,b,c。把卡牌分為x,y兩類,分別有n1,n2張。
兩張卡牌能夠配對,當且僅當,存在至多一項屬性值使得兩張卡牌該項屬性值互質,且兩張卡牌類別不同。
比如一張x類卡牌屬性值分別是225,233,101,一張y類卡牌屬性值分別為115,466,99。那麼這兩張牌是可以配對的,因為只有101和99一組屬性互質。
遊戲的目的是最大化匹配上的卡牌組數,當然每張卡牌只能用一次。
資料第一行兩個數n1,n2,空格分割。
接下來n1行,每行3個數,依次表示每張x類卡牌的3項屬性值。
接下來n2行,每行3個數,依次表示每張y類卡牌的3項屬性值。
輸出乙個整數:最多能夠匹配的數目。
2 22 2 2
2 5 5
2 2 5
5 5 5
2【提示】
樣例中第一張x類卡牌和第一張y類卡牌能配對,第二張x類卡牌和兩張y類卡牌都能配對。所以最佳方案是第一張x和第一張y配對,第二張x和第二張y配對。
另外,請大膽使用漸進複雜度較高的演算法!
對於100%的資料,n1,n2≤ 30000,屬性值為不超過200的正整數
第一眼看得出是二分圖匹配···然而暴力建邊果斷t
不得不說建邊的方法太nb···其實通過屬性值不超過200是可以想到分解質因數的···
另外不得不說自己**能力好弱····打這題調了半天····
引用hzwer的題解,orz····
考慮到按照匹配建圖邊數過多,我們採用將邊分類的方法優化。考慮a項屬性值能被x整除且b項能力值能被y整除的所有點,只要是在兩側一定能夠匹配,所以我們在匹配的網路流模型中間增加一排這樣的點,滿足要求的左右點分別與它相連,邊權為正無窮。考慮到x和y只需是質數,這樣的點共有至多3*46*46個(1~200質數共46個),而200<2*3*5*7,所以兩側每個點至多連出3*3*3條邊。於是我們構成了乙個70000個點,2000000條邊的網路流,依然是分層圖,所以dinic有極佳的速度優勢,通過100分資料。
#include#include#include
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
const
int n=2*30005+46*46*3
;const
int m=8000005
;vector
num[5000
];struct
node
carda[
30005],cardb[30005
];int n1,n2,prime[205],cnt,ans=0
;int first[n],next[m],go[m],rest[m],lev[n],cur[n],tot=1,src,des,id[50][50
];bool notprime[5000
];int
r()void
pre()
for(int i=2;i<=200;i++)
for(int j=1;j<=cnt;j++)
if(i%prime[j]==0
) num[i].push_back(j);
}inline
void comb(int a,int b,int
c)inline
void build1(intu)
inline
void build2(int
u)inline
bool
bfs()
}}
return
false;}
inline
int dinic(int u,int
flow)
}}
if(res!=flow) lev[u]=-1;
return
res;
}inline
void
maxflow()
intmain()
bzoj4205 卡牌配對
卡牌配對 題目背景 bzoj4205 分析 我相信很多人第一反應都是暴力連邊然後暴力二分圖匹配,然後我的常數還沒有小到n2過 30000 所以我們來想想該怎麼辦,考慮到 200以內的質數只有 46個,我們可以選擇增加 3 46 46 個點,將左邊的某種屬性有第 i個質因數,另乙個屬性有第 j個質因數...
BZOJ4205 卡牌配對
對於兩張卡牌,如果存在兩種屬性值不互質,則可以匹配。只考慮200以內的質數,一共有46個,可以新建3 46 46個點來表示一類屬性值中有這兩種質數的卡牌。然後對於每張卡牌,列舉它的質因子,最多只有3個,如此建圖求出最大流即可。includeconst int n 66500,inf 0u 2,p 2...
BZOJ4205 卡牌配對
現在有一種卡牌遊戲,每張卡牌上有三個屬性值 a,b,c。把卡牌分為x,y兩類,分別有n1,n2張。兩張卡牌能夠配對,當且僅當,存在至多一項屬性值使得兩張卡牌該項屬性值互質,且兩張卡牌類別不同。比如一張x類卡牌屬性值分別是225,233,101,一張y類卡牌屬性值分別為115,466,99。那麼這兩張...