yesky wine供應系統題解【二分圖匹配】
阿新 • • 發佈:2020-06-22
4513: yesky wine供應系統
Time Limit:1 SecMemory Limit:128 MBSubmit:34Solved:6
Description
自從上次懶羊羊紅酒促銷會後,越來越多的羊族及朋友喜歡上了yesky wine。懶羊羊跟葉老師申請要銷售更多的yesky wine紅酒。為此,他還準備改造他的紅酒供應系統。紅酒供應系統由一個酒廠,一個紅酒儲藏站,若干供應站和管道組成。當然,酒廠就位於葉老師所在的浙江理工大學後花園。中轉站位於懶羊羊開設的很多酒吧、餐廳和其他紅酒供應場所,需要時可以銷售。紅酒儲藏站的位置非常神祕,不過這個對整個系統不是很重要。
紅酒供應管道連線了剛才提到的各站點。酒廠至少連線了1個站點,神祕的儲藏站也至少連線了一個站點。當然,極端的情況下,可能酒廠直接連線到神祕的儲藏站,而沒有其他任何中轉站。
紅酒在系統裡流動,從某個站點流出的紅酒不會返回到該站點,也就是說系統中不會出現迴路。管道中酒的流向也是固定的不會迴流。酒廠的酒是足夠的,管道中的經常是有紅酒流的。
現在的紅酒供應系統有一些管道是多餘的。你需要對這些管道進行優化,去掉一些多餘的管道使得每個中轉站都能得到紅酒供應,同時也能流轉到神祕的儲藏站。當然,管道的容量是足夠大的。
給你這個供酒系統的佈置圖,你能幫懶羊羊看看最多可以去掉多少根管道嗎?
Input
第一行輸入2個整數N,M(1<=N<=2000,0<=M<=5000),N是系統中紅酒站點,包括酒廠和儲藏站。M是管道數量。站點用1,2,...N標記。
Output
輸出一個整數,表示可以去掉多餘的最大管道數
Sample Input
【樣例輸入1】 5 6 2 4 3 5 2 5 1 4 2 3 5 1 【樣例輸入2】 4 4 1 2 1 3 2 4 3 4
Sample Output
【樣例輸出1】 2 【樣例輸出2】 0
HINT
Source
思路
感覺這才是本場簽到題,可惜被C搞了心態沒看題
這道題給人的感覺就是要往二分圖上想
給出一個有源有匯的有向無環圖,問如何用最少的邊把整張圖跑滿
因為題目保證了能流滿(∵系統中有多餘的管道)
在此前提下,僅需要保證圖在最少的連邊情況下跑通即可
何為最少:刪去一條邊則有站點未被經過,可以看做是未達到最大流
那麼可得到 要求1:最少時,每個中轉站至少有一個入點和一個出點
我們通過觀察可以發現,此時求最大流的過程就相當於每兩個中轉站之間去架設管道匹配
為了方便操作,我們使用匈牙利演算法來計算必須參與匹配的管道數
對於沒有達到要求1的中轉站,我們把他本來連線的但此時暫未選入的管道加入網路中,來保證我們的圖可以跑通
CODE
1 #include <bits/stdc++.h> 2 #define dbg(x) cout << #x << "=" << x << endl 3 #define eps 1e-8 4 #define pi acos(-1.0) 5 6 using namespace std; 7 typedef long long LL; 8 9 template<class T>inline void read(T &res) 10 { 11 char c;T flag=1; 12 while((c=getchar())<‘0‘||c>‘9‘)if(c==‘-‘)flag=-1;res=c-‘0‘; 13 while((c=getchar())>=‘0‘&&c<=‘9‘)res=res*10+c-‘0‘;res*=flag; 14 } 15 16 const int maxn = 2e3 + 5; 17 const int inf = 0x3f3f3f3f; 18 19 int n,m,e; 20 int vis[maxn][maxn]; 21 int ask[maxn]; 22 int cnt,ans; 23 int matched[maxn]; 24 int in1[maxn],out1[maxn];//匹配後每個點出入度 25 int in[maxn],out[maxn];//匹配前每個點的出入度 26 27 bool fid(int x) { 28 for (int i = 1 ; i <= n; i++) 29 if (vis[x][i]) { 30 if (ask[i]) 31 continue; 32 ask[i] = 1; 33 if (!matched[i] || fid(matched[i])) { 34 matched[i] = x ; 35 in1[i]++; 36 out1[x]++; 37 return true; 38 } 39 } 40 return false; 41 } 42 43 void match() { 44 cnt = 0; 45 memset(matched,0,sizeof(matched)); 46 for(int i = 1; i <= n; ++i) { 47 memset(ask,sizeof(ask)); 48 if(fid(i)) { 49 cnt++; 50 } 51 } 52 ans = cnt; 53 } 54 55 56 57 int main() 58 { 59 read(n); read(m); 60 cnt = 0; 61 for(int i = 1; i <= m; i++) { 62 int x,y; 63 read(x); read(y); 64 in[y]++; 65 out[x]++; 66 vis[x][y] = 1; 67 } 68 match(); 69 // for ( int i = 1; i <= n; ++i ) { 70 // printf("match[%d]:%d\n",i,matched[i]); 71 // } 72 // puts(""); 73 for ( int i = 1; i <= n; ++i ) { 74 //printf("out1[%d]:%d in1[%d]:%d\n",out1[i],in1[i]); 75 if(in[i] && !out[i]) {//T 76 if(in1[i] == 0) { 77 in1[i] = 1; 78 ++ans; 79 } 80 continue; 81 } 82 if(!in[i] && out[i]) { 83 if(out1[i] == 0) { 84 out1[i] = 1; 85 ++ans; 86 } 87 continue; 88 } 89 if(in[i] && out[i]) { 90 if(in1[i] == 0) { 91 ++ans; 92 in1[i] = 1; 93 } 94 if(out1[i] == 0) { 95 ++ans; 96 out1[i] = 1; 97 } 98 continue; 99 } 100 } 101 cout << m - ans << endl; 102 //printf("%d\n",ans); 103 104 return 0; 105 }View Code #include<bits/stdc++.h> #definedbg(x)cout<<#x<<"="<<x<<endl #defineeps1e-8 #definepiacos(-1.0) usingnamespacestd; typedeflonglongLL; template<classT>inlinevoidread(T&res) { charc;Tflag=1; while((c=getchar())<‘0‘||c>‘9‘)if(c==‘-‘)flag=-1;res=c-‘0‘; while((c=getchar())>=‘0‘&&c<=‘9‘)res=res*10+c-‘0‘;res*=flag; } constintmaxn=2e3+5; constintinf=0x3f3f3f3f; intn,e; intvis[maxn][maxn]; intask[maxn]; intcnt,ans; intmatched[maxn]; intin1[maxn],out1[maxn];//匹配後每個點出入度 intin[maxn],out[maxn];//匹配前每個點的出入度 boolfid(intx){ for(inti=1;i<=n;i++) if(vis[x][i]){ if(ask[i]) continue; ask[i]=1; if(!matched[i]||fid(matched[i])){ matched[i]=x; in1[i]++; out1[x]++; returntrue; } } returnfalse; } voidmatch(){ cnt=0; memset(matched,0,sizeof(matched)); for(inti=1;i<=n;++i){ memset(ask,sizeof(ask)); if(fid(i)){ cnt++; } } ans=cnt; } intmain() { read(n);read(m); cnt=0; for(inti=1;i<=m;i++){ intx,y; read(x);read(y); in[y]++; out[x]++; vis[x][y]=1; } match(); //for(inti=1;i<=n;++i){ //printf("match[%d]:%d\n",matched[i]); //} //puts(""); for(inti=1;i<=n;++i){ //printf("out1[%d]:%din1[%d]:%d\n",in1[i]); if(in[i]&&!out[i]){//T if(in1[i]==0){ in1[i]=1; ++ans; } continue; } if(!in[i]&&out[i]){ if(out1[i]==0){ out1[i]=1; ++ans; } continue; } if(in[i]&&out[i]){ if(in1[i]==0){ ++ans; in1[i]=1; } if(out1[i]==0){ ++ans; out1[i]=1; } continue; } } cout<<m-ans<<endl; //printf("%d\n",ans); return0; }