日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【BZOJ4205】卡牌配对 最大流

發布時間:2025/3/15 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【BZOJ4205】卡牌配对 最大流 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【BZOJ4205】卡牌配對

Description

現在有一種卡牌游戲,每張卡牌上有三個屬性值:A,B,C。把卡牌分為X,Y兩類,分別有n1,n2張。 兩張卡牌能夠配對,當且僅當,存在至多一項屬性值使得兩張卡牌該項屬性值互質,且兩張卡牌類別不同。 比如一張X類卡牌屬性值分別是225,233,101,一張Y類卡牌屬性值分別為115,466,99。那么這兩張牌是可以配對的,因為只有101和99一組屬性互質。 游戲的目的是最大化匹配上的卡牌組數,當然每張卡牌只能用一次。

Input

數據第一行兩個數n1,n2,空格分割。 接下來n1行,每行3個數,依次表示每張X類卡牌的3項屬性值。 接下來n2行,每行3個數,依次表示每張Y類卡牌的3項屬性值。

Output

輸出一個整數:最多能夠匹配的數目。

Sample Input

2 2
2 2 2
2 5 5
2 2 5
5 5 5

Sample Output

2
【提示】
樣例中第一張X類卡牌和第一張Y類卡牌能配對,第二張X類卡牌和兩張Y類卡牌都能配對。所以最佳方案是第一張X和第一張Y配對,第二張X和第二張Y配對。
另外,請大膽使用漸進復雜度較高的算法!

HINT

對于100%的數據,n1,n2≤ 30000,屬性值為不超過200的正整數

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

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

#include <cstdio> #include <cstring> #include <iostream> #include <queue> #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]; queue<int> q; inline int rd() {int ret=0,f=1; char gc=getchar();while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();return ret*f; } void work(int a,int val) {tp[a]=0;for(int i=1;pri[i]*pri[i]<=val;i++){if(val%pri[i]==0){v[a][++tp[a]]=i;while(val%pri[i]==0) val/=pri[i];}}if(val!=1) v[a][++tp[a]]=np[val]; } void add(int a,int b,int c) {to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;to[cnt]=a,val[cnt]=0,next[cnt]=head[b],head[b]=cnt++; } int dfs(int x,int mf) {if(x==T) return mf;int i,k,temp=mf;for(i=head[x];i!=-1;i=next[i]){if(d[to[i]]==d[x]+1&&val[i]){k=dfs(to[i],min(temp,val[i]));if(!k) d[to[i]]=0;val[i]-=k,val[i^1]+=k,temp-=k;if(!temp) break;}}return mf-temp; } int bfs() {memset(d,0,sizeof(d));while(!q.empty()) q.pop();q.push(S),d[S]=1;int i,u;while(!q.empty()){u=q.front(),q.pop();for(i=head[u];i!=-1;i=next[i]){if(!d[to[i]]&&val[i]){d[to[i]]=d[u]+1;if(to[i]==T) return 1;q.push(to[i]);}}}return 0; } int main() {n1=rd(),n2=rd(),S=n1+n2+1,T=n1+n2+2;int i,j,a,b,c;for(i=2;i<=200;i++){if(!np[i]) pri[++num]=i,np[i]=num;for(j=1;j<=num&&i*pri[j]<=200;j++){np[i*pri[j]]=1;if(i%pri[j]==0) break;}}memset(head,-1,sizeof(head));for(i=1;i<=n1;i++){a=rd(),b=rd(),c=rd();work(0,a),work(1,b),work(2,c),add(S,i,1);for(a=1;a<=tp[0];a++) for(b=1;b<=tp[1];b++) add(i,P(0,v[0][a],v[1][b]),1);for(a=1;a<=tp[0];a++) for(b=1;b<=tp[2];b++) add(i,P(1,v[0][a],v[2][b]),1);for(a=1;a<=tp[1];a++) for(b=1;b<=tp[2];b++) add(i,P(2,v[1][a],v[2][b]),1);}for(i=1;i<=n2;i++){a=rd(),b=rd(),c=rd();work(0,a),work(1,b),work(2,c),add(i+n1,T,1);for(a=1;a<=tp[0];a++) for(b=1;b<=tp[1];b++) add(P(0,v[0][a],v[1][b]),i+n1,1);for(a=1;a<=tp[0];a++) for(b=1;b<=tp[2];b++) add(P(1,v[0][a],v[2][b]),i+n1,1);for(a=1;a<=tp[1];a++) for(b=1;b<=tp[2];b++) add(P(2,v[1][a],v[2][b]),i+n1,1);}while(bfs()) ans+=dfs(S,1<<30);printf("%d",ans);return 0; }

轉載于:https://www.cnblogs.com/CQzhangyu/p/7468943.html

新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!

總結

以上是生活随笔為你收集整理的【BZOJ4205】卡牌配对 最大流的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。