卡牌配對
題目背景:
bzoj4205
分析:我相信很多人第一反應都是暴力連邊然後暴力二分圖匹配,然後我的常數還沒有小到n2過
30000
,所以我們來想想該怎麼辦,考慮到
200以內的質數只有
46個,我們可以選擇增加
3 * 46 * 46
個點,將左邊的某種屬性有第
i個質因數,另乙個屬性有第
j個質因數的點連向對應的乙個點,並將這個點與右邊滿足上述條件的點相連,然後新建源點匯點就可以跑最大流了,大概是乙個
70000
個點,2000000
條邊的網路流(
200以內的數最多
3個質因數,所以最多不超過
27條邊),他竟然讓大膽玩高漸進複雜度,那當然就直接上吧。
source:
/*
created by scarlyw
*/#include #include #include #include #include #include #include #include #include #include inline char read()
return *s++;}
///*
templateinline void r(t &x)
for (x = 0; isdigit(c); c = read())
x = ((x << 2) + x << 1) + (c ^ '0');
if (iosig) x = -x;
}//*/
const int out_len = 1024 * 1024;
char obuf[out_len], *oh = obuf;
inline void write_char(char c)
templateinline void w(t x) }
inline void flush()
/*templateinline void r(t &x)
//*/
const int maxn = 70000 + 10;
const int maxx = 200 + 5;
const int prime[50] = ;
struct node
} ;
struct data x[maxn], y[maxn];
std::vectoredge[maxn];
int n1, n2, n, s, t;
int id[3][maxx][maxx], dis[maxn], gap[maxn];
inline void add_edge(int x, int y, int w)
inline void read_in()
inline int solve(int n, int *a)
if (n != 1) a[++top] = n;
return top;}
inline void build_graph()
for (int i = 1; i <= n2; ++i) }
///*
inline int sap(int cur, int flow, int s, int t, int n)
}if (--gap[dis[cur]] == 0) dis[s] = n;
return gap[++dis[cur]]++, temp[cur] = 0, del;}
inline int sap(int s, int t, int n)
//*/
int main()
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。那麼這兩張...
BZOJ4205 卡牌配對(網路流)
現在有一種卡牌遊戲,每張卡牌上有三個屬性值 a,b,c。把卡牌分為x,y兩類,分別有n1,n2張。兩張卡牌能夠配對,當且僅當,存在至多一項屬性值使得兩張卡牌該項屬性值互質,且兩張卡牌類別不同。比如一張x類卡牌屬性值分別是225,233,101,一張y類卡牌屬性值分別為115,466,99。那麼這兩張...