BZOJ4205 卡牌配對 最大流

2022-05-20 08:12:51 字數 1586 閱讀 2774

現在有一種卡牌遊戲,每張卡牌上有三個屬性值: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的正整數

題解:這個建模題有點難想~

先只考慮a和b都不互質的情況,因為200以內的質數只有46個,並且每個數所含的不同的質因子不超過3個,所以建46*46個點,每個a中的卡牌向所有自己包含的質數對連邊,最多3*3條邊。然後在分別考慮其他情況,只需要對a和b,a和c,b和c都建46*46個點即可。然後跑最大流既是答案。

#include #include #include #include #define p(a,b,c) ((a)*num*num+(b-1)*num+c+t)

using namespace std;

int n1,n2,s,t,cnt,ans,num;

int v[3][10],tp[3];

int pri[210],np[210];

int head[70000],d[70000],to[2000000],next[2000000],val[2000000];

queueq;

inline int rd()

while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();

return ret*f;

}void work(int a,int val)

} if(val!=1) v[a][++tp[a]]=np[val];

}void add(int a,int b,int c)

int dfs(int x,int mf)

} return mf-temp;

}int bfs()

} }return 0;

}int main()

} memset(head,-1,sizeof(head));

for(i=1;i<=n1;i++)

for(i=1;i<=n2;i++)

while(bfs()) ans+=dfs(s,1<<30);

printf("%d",ans);

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。那麼這兩張...