【BZOJ4375】Selling Tickets 隨機化
阿新 • • 發佈:2017-09-03
line 賣出 ets -s 每次 感到 mil 分隔 針對
6 4
1 2
1 2
3 4
5 6
6 5
1 2
1 2
1 2
3 4
5 6
4 5
1 2
1 3
1 4
2 3
3 4
2
4 1≤Ai, Bi≤n且Ai≠Bi
【BZOJ4375】Selling Tickets
Description
廚師在一次晚宴上準備了n道豐盛的菜肴,來自世界各地的m位顧客想要購買宴會的門票。每一位顧客都有兩道特別喜愛的菜,而只要吃到了至少一道他喜愛的菜,這位顧客就會感到很高興。當然,每道菜最多只能供應給一位顧客。廚師想要賣出盡可能多的門票,但同時要能夠保證,無論哪些顧客購買門票,所有到來的顧客都能感到高興。現在,廚師想要問你,他最多能夠賣多少門票?
Input
輸入的第一行包含一個正整數T,表示數據組數。
對於每組數據,第一行包含一對整數n和m,分別表示菜肴的數量與顧客的數量。接下來m行,第i行的兩個正整數Ai, Bi代表第i位顧客喜愛的兩道菜的編號。相鄰的兩組數據之間用一個空行分隔。
Output
輸出總共T行,對於每組數據,輸出一個整數,表示廚師最多能售出的門票數。
Sample Input
36 4
1 2
1 2
3 4
5 6
6 5
1 2
1 2
1 2
3 4
5 6
4 5
1 2
1 3
1 4
2 3
3 4
Sample Output
42
4
HINT
對於第二組數據,廚師不能賣3張門票。因為如果顧客1, 2, 3購買門票,廚師是不可能用菜肴1, 2滿足三個顧客的要求的。
【數據規模與約定】
1≤T≤15, 2≤n≤200, 0≤m≤500
題解:我想不出正解,居然采用隨機化;並且隨機化寫掛了,還針對數據進行隨機化,我真是太無恥了~
簡單的想法就是每次random_shuffle一個序列,沿著這個序列從左到右一直賣,如果賣到第i+1個賣不出去了,就用i更新答案。如何判定能不能賣出去呢?二分圖最大匹配即可。
但是這種隨機化策略實在是naive,我們考慮優化,如果賣到i+1個賣不出去了,我們看一下第i+1個人在二分圖最大匹配上一共試圖匹配了多少個人,即交錯環的大小。並用交錯環的大小來更新答案,然後就切了~
#include <cstdio> #include <cstring> #include <iostream> #include <queue> #include <algorithm> using namespace std; int n,m,S,T,ans,cnt,now,sum; int A[510],B[510],vis[510],head[1010],p[1010],to[10010],next[10010],from[210]; void add(int a,int b) { to[cnt]=b,next[cnt]=head[a],head[a]=cnt++; } 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; } int dfs(int x) { sum++; for(int i=head[x];i!=-1;i=next[i]) { if(vis[to[i]]!=now) { vis[to[i]]=now; if(!from[to[i]]||dfs(from[to[i]])) { from[to[i]]=x; return 1; } } } return 0; } void work() { srand(1011); n=rd(),m=rd(),ans=m; int i,j,a,b; memset(head,-1,sizeof(head)),cnt=0,memset(vis,0,sizeof(vis)),now=0; for(i=1;i<=m;i++) a=rd(),b=rd(),add(i,a),add(i,b),p[i]=i; for(i=1;i<=2000;i++) { random_shuffle(p+1,p+m+1); memset(from,0,sizeof(from)); for(j=1;j<=m;j++) { now++,sum=0; if(!dfs(p[j])) { ans=min(ans,sum-1); break; } } } printf("%d\n",ans); } int main() { int T=rd(); while(T--) work(); return 0; }//3 6 4 1 2 1 2 3 4 5 6 6 5 1 2 1 2 1 2 3 4 5 6 4 5 1 2 1 3 1 4 2 3 3 4
【BZOJ4375】Selling Tickets 隨機化