【問題描述】ios
咱們知道機器調度是計算機科學中一個很是經典的問題。調度問題有不少種,具體條件不一樣,問題就不一樣。如今咱們要處理的是兩個機器的調度問題。算法
有兩個機器A和B。機器A有n種工做模式,咱們稱之爲mode_0,mode_l,……,mode_n-1。一樣,機器B有m種工做模式,咱們稱之爲mode_0,mode_1,……,mode_m-1。初始時,兩臺機器的工做模式均爲mode_0。如今有k個任務,每一個工做均可以在兩臺機器中任意一臺的特定的模式下被加工。例如,job0能在機器A的mode_3或機器B的mode_4下被加工,jobl能在機器A的mode_2或機器B的mode_4下被加工,等等。所以,對於任意的jobi,咱們能夠用三元組(i,x,y)來表示jobi在機器A的mode_x或機器B的mode_y下被加工。ide
顯然,要完成全部工做,咱們須要不時的改變機器的工做模式。可是,改變機器的工做狀態就必須重啓機器,這是須要代價的。你的任務是,合理的分配任務給適當的機器,使機器的重啓次數儘可能少。spa
【輸入】string
第一行三個整數n,m(n,m<100),k(k<1000)。接下來的k行,每行三個整數i,x,y。it
【輸出】io
只一行一個整數,表示最少的重啓次數。class
【樣例】stream
machine.in machine.out計算機科學
5 5 10 3
0 1 1
1 1 2
2 1 3
3 1 4
4 2 1
5 2 2
6 2 3
7 2 4
8 3 3
9 4 3
【問題分析】
本題所求的是工做模式的最少切換次數,實際上也就是求最少須要使用多少個工做模式,由於一個工做模式被切換兩次確定是不合算的,一旦切換到一個工做模式就應該把這個工做模式能夠完成的工做都完成。
將兩臺機器的工做模式分別當作n個和m個節點。jobi分別和機器A和B的mode_x和mode_y相關:jobi要被完成,就必須切換到機器A的mode_x或切換到機器B的mode_y。將jobi看做圖中的一條邊——鏈接節點x和節點y的邊,那麼這條邊就要求x和y兩個節點中至少要有一個節點被取出來。這正符合覆蓋集的性質。
咱們構成的圖是二分圖,要求最少的切換次數,就是要使覆蓋集最小。二分圖的最小覆蓋集問題等價於二分圖的最大匹配問題。所以,只需對此二分圖求一個最大匹配便是咱們要求的答案。時間複雜度。
//二部圖 匈牙利算法 #include<cstdio> #include<iostream> #include<cstring> #define M 30 using namespace std; int g[M][M],link[M],used[M],n,m,k; int path(int i) { if(used[i])return 0; used[i]=1; for(int j=1;j<=m;j++) if(g[i][j]&&(!link[j]||path(link[j]))) { link[j]=i; return 1; } return 0; } int main() { scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=k;i++) { int temp,x,y; scanf("%d%d%d",&temp,&x,&y); if(x&&y)g[x][y]=1; } for(int i=1;i<=n;i++) if(path(i)) memset(used,0,sizeof(used)); int tot=0; for(int i=1;i<=m;i++) if(link[i])tot++; printf("%d",tot); return 0; }