BZOJ4405 [wc2016]挑戰NPC

來源:互聯網
上載者:User

標籤:names   注意   nbsp   pac   聲明   ast   first   二分圖   swap   

本文著作權歸ljh2000和部落格園共有,歡迎轉載,但須保留此聲明,並給出原文連結,謝謝合作。

 

 

本文ljh2000 
作者部落格:http://www.cnblogs.com/ljh2000-jump/
轉載請註明出處,侵權必究,保留最終解釋權!

 Description小N最近在研究NP完全問題,小O看小N研究得熱火朝天,便給他出了一道這樣的題目:有n個球,用整數1到n編號。還有m個筐子,用整數1到m編號。每個筐子最多能裝3個球。每個球只能放進特定的筐子中。具體有e個條件,第i個條件用兩個整數vi和ui描述,表示編號為vi的球可以放進編號為ui的筐子中。每個球都必須放進一個筐子中。如果一個筐子內有不超過1個球,那麼我們稱這樣的筐子為半空的。求半空的筐子最多有多少個,以及在最優方案中,每個球分別放在哪個筐子中。小N看到題目後瞬間沒了思路,站在旁邊看熱鬧的小I嘿嘿一笑:“水題!”然後三言兩語道出了一個多項式演算法。小N瞬間就驚呆了,三秒鐘後他回過神來一拍桌子:“不對!這個問題顯然是NP完全問題,你演算法肯定有錯!”小I淺笑:“所以,等我領圖靈獎吧!”小O只會出題不會做題,所以找到了你——請你對這個問題進行探究,並寫一個程式解決此題。 Input第一行包含1個正整數T,表示有T組資料。對於每組資料,第一行包含3個正整數n,m,e,表示球的個數,筐子的個數和條件的個數。接下來e行,每行包含2個整數vi,ui,表示編號為vi的球可以放進編號為ui的筐子。Output

 對於每組資料,先輸出一行,包含一個整數,表示半空的筐子最多有多少個。

Sample Input1
4 3 6
1 1
2 1
2 2
3 2
3 3
4 3
Sample Output2HINT

 

 對於所有資料,T≤5,1≤n≤3m。保證 1≤vi≤n,1≤ui≤m,且不會出現重複的條件。


保證至少有一種合法方案,使得每個球都放進了筐子,且每個筐子內球的個數不超過 3。
M<=100  正解:建圖+一般圖最大匹配(帶花樹)解題報告:  這道題明明是一道巧妙建圖+一般圖最大匹配的模板題,出題人強行賣萌居然說是NPC演算法...  我才不會說我學帶花樹之前也真以為這道題是NPC演算法呢...  顯然這道題和一般圖的最大匹配有關,但是有一定的限制,所以關鍵在於如何建圖,才能使得求出放球的數量<=1的框的數量。  先講一講各個部分分吧...   演算法一:    測試點1、2範圍很小,暴搜即可;   演算法二:    當e=nm的時候即每個球都可以放在任意一個框中,那麼答案唯一確定,方案的話只要先每個放一個,再一個一個放滿,這樣構造即可得到最優;   演算法三:    測試點4說,存在方案使得m個框均為半空,那麼即每個框確保可以最多放一個球,直接連邊跑二分圖匹配即可;   演算法四:    不存在有半空的框的方案,即每一個框都至少有2個球,則把每個框拆成三個跑二分圖匹配即可。     最後講正解辣:把每個框拆成三個,這三個之間互相連邊,每個能放入這個框的球再與這三個拆掉的點連邊,跑一般圖最大匹配,帶花樹跑完之後得到全圖的最大匹配,答案即為$maxMatch-n$。  這是為什麼呢?  建圖之後,經過觀察,對於一個框而言:假如不放球,則最大匹配為1;放入一個球時,最大匹配為2;放入兩個球時,最大匹配為2;放入三個球時,最大匹配為3。  容易發現對於每個框而言,不妨設這個框內放的球數為num,那麼maxMatch-num即為這個框產生的貢獻。這題的關鍵在於建圖,建圖好神奇好巧妙啊QAQ。不過我對於帶花樹的模板還不夠熟練,還是要花時間多看一下,加深理解。  ps:這道題有一個很關鍵的問題:就是我必須從N for到1!我必須先匹配球!因為我需要保證球先被匹配,如果我先匹配框的話的確可以保證總匹配數不變,但是有一些框就和另一些框匹配了,而球卻落單了。這個問題如果不注意的話只有40分...   
//It is made by ljh2000#include <iostream>#include <cstdlib>#include <cstring>#include <cstdio>#include <cmath>#include <algorithm>using namespace std;typedef long long LL;const int MAXN = 1211;const int MAXM = 1000011;int N,n,m,E,ecnt,first[MAXN],to[MAXM],next[MAXM],match[MAXN],pre[MAXN],vis[MAXN],Tim,dui[MAXM],head,tail,id[MAXN],Match,father[MAXN],ans;inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x; }inline int find(int x){ if(father[x]!=x) father[x]=find(father[x]); return father[x]; }inline int getint(){    int w=0,q=0; char c=getchar(); while((c<‘0‘||c>‘9‘) && c!=‘-‘) c=getchar();    if(c==‘-‘) q=1,c=getchar(); while (c>=‘0‘&&c<=‘9‘) w=w*10+c-‘0‘,c=getchar(); return q?-w:w;}inline int lca(int x,int y){Tim++;while(vis[x]!=Tim) {if(x){x=find(x);if(vis[x]==Tim) return x;vis[x]=Tim;if(match[x]!=0) x=find(pre[match[x]]);//!!!else x=0;}swap(x,y);}return x;}inline void change(int x,int y,int k){while(find(x)!=k) {pre[x]=y; int z=match[x];//!!!if(id[z]==1) { id[z]=0; dui[++tail]=z; }if(find(z)==z) father[z]=k;if(find(x)==x) father[x]=k;y=z; x=pre[y];}}inline bool bfs(int s){for(int i=1;i<=N;i++) id[i]=-1,father[i]=i; head=tail=0;dui[++tail]=s; id[s]=0; int u;while(head<tail) {head++; u=dui[head];for(int i=first[u];i;i=next[i]) {int v=to[i];if(id[v]==-1) {pre[v]=u; id[v]=1;if(!match[v]) {int last,t,now=v;while(now!=0) {t=pre[now];last=match[t]; match[t]=now; match[now]=t;now=last;}return true;}id[match[v]]=0; dui[++tail]=match[v];}else if(id[v]==0/*!!!*/ && find(u)!=find(v)) {int g=lca(u,v);change(u,v,g);change(v,u,g);}}}return false;}inline void work(){int T=getint(); int x,y;while(T--) {n=getint(); m=getint(); E=getint(); ecnt=0; memset(first,0,sizeof(first));for(int i=1;i<=E;i++) {x=getint(); y=getint(); x+=3*m;link(x,(y-1)*3+1);link(x,(y-1)*3+2);link(x,(y-1)*3+3);}for(int i=1;i<=m;i++) {//每個框內部連邊int base=(i-1)*3+1;link(base,base+1);link(base,base+2);link(base+1,base+2);}N=n+3*m; memset(match,0,sizeof(match)); memset(pre,0,sizeof(pre));Tim=0; memset(vis,0,sizeof(vis)); Match=0;//!!!for(int i=N;i>=1;i--) if(!match[i] && bfs(i)) Match++;ans=Match-n;printf("%d\n",ans);}}int main(){    work();    return 0;}

  

BZOJ4405 [wc2016]挑戰NPC

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.