現在有一種卡牌遊戲,每張卡牌上有三個屬性值: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的正整數
又一道場上想不出來的題。
首先考慮普通網路流匹配:左邊是一類卡牌,右邊是另一類卡牌,兩兩之間看能否配對連一條容量為1的邊,做一次dinic出解。
但是完整資料中兩邊點數都是3萬,肯定無法兩兩連邊。這時候我們想到優化建圖:我們肯定是要構造一些特殊資訊點,將符合資訊的卡牌分別連向它們,以此減少邊數、完成匹配。
照例從源點向每乙個x卡牌連一條容量為1的邊,每乙個y卡牌向匯點連一條容量為1的邊,限制匹配次數。
考慮中間輔助匹配的資訊點是什麼:至多一組數互質等價於至少兩組數不互質。不互質,意味著有公約數;而至少兩組數的話,我們可以分拆成三種情況:一對卡牌的ab滿足條件、ac滿足條件、bc滿足條件。
公約數怎麼處理?我們可以把所有公約數二元組看成乙個資訊點。以12為例,我們在中間建一列資訊點\((x,y)\),所有滿足\(x|a\)且\(y|b\)的x卡牌向這個點連一條容量為1的邊,相應地從這個點向滿足條件的y卡牌連一條容量為1的邊。我們發現,這樣恰好可以使得滿足ab都不互質的卡牌們進行配對過程。
同理建出其他兩組資訊點。三組資訊點同時存在時,我們發現不論如何,一張x卡牌最多通過一種方式也就是一組資訊點和另一邊的某一張y卡牌配對,同樣地y卡牌不論如何也只會通過一種方式配對。即使是abc都滿足的一對卡牌,也最多隻會選擇從某一組資訊點流過。
建模完成,過程優美。
但是\((x,y)\)的點數足足有\(3*200*200\)個,太多了。其實有公約數不就是有公質因子嗎?200以內的素數僅僅有46個,所以現在我們只需要把資訊點的\((x,y)\)變更成質數的組合\((p_i,p_j)\),按上述連邊即可。資訊點點數僅僅有\(3*46*46=6348\)個。
dinic是跑得過的,有極大的速度優勢。
#include #include using namespace std;
const int n=30005,inf=1000000000,sz=68000,m=6000000;
int p[n],pcnt,minp[n],id[n];
bool vis[n];
int n1,n2,a[n*2][3];
int h[sz],tot=1;
int s,t,dis[sz],cur[sz];
queueq;
struct edgee[m*2];
inline void addedge(int u,int v,int f); h[u]=tot;
e[++tot]=(edge); h[v]=tot;
}void sieve()
for(int j=1;j<=pcnt&&i*p[j]<=200;j++)
minp[x]=p[j];}}
}bool bfs()
}return dis[t]!=-1;
}int dfs(int u,int flow)
if(!res) dis[u]=-1;
return res;
}int dinic()
void deal(int x,int *l,int &cnt)
}int main()
for(int i=1;i<=t1;i++)
for(int j=1;j<=t3;j++)
for(int i=1;i<=t2;i++)
for(int j=1;j<=t3;j++)
}printf("%d\n",dinic());
return 0;
}
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。那麼這兩張...