HDOJ---2236 无题II[二分枚举+匈牙利]
生活随笔
收集整理的這篇文章主要介紹了
HDOJ---2236 无题II[二分枚举+匈牙利]
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
無題II
Time Limit: 2000/2000 MS (Java/Others)????Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 571????Accepted Submission(s): 296
?
Input 輸入一個整數(shù)T表示T組數(shù)據(jù)。對于每組數(shù)據(jù)第一行輸入一個正整數(shù)n(1<=n<=100)表示矩陣的大小。
接著輸入n行,每行n個數(shù)x(0<=x<=100)。
?
Output 對于每組數(shù)據(jù)輸出一個數(shù)表示最小差值。?
Sample Input 1 4 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4?
Sample Output 3?
Author xhd?
Source HDOJ 2008 Summer Exercise(2)- Hold by Captain Xu?
Recommend lcy code : 1 /* 2 為了保證每行每列只取一個元素,我們可以從二分圖最大匹配的思想入手,把行和列分別看做二分圖左右兩部分, 3 i-j的邊權(quán)就是第i行第j列的元素的值。這樣構(gòu)圖之后,求得的二分圖最大匹配的4條邊就是不在同行或同列的4個元素。 4 有了這個思想時候,我們只需要再保證4個元素中最大值與最小值之差盡量小就可以了,于是我們可以二分枚舉最大值與最小值之差, 5 并枚舉邊權(quán)值的下界,如果枚舉到某個邊權(quán)值的下界時該圖存在最大匹配,那么就更新max,否則就更新min。 6 */ 7 #include <iostream> 8 #include <iomanip> 9 #include <fstream> 10 #include <sstream> 11 #include <algorithm> 12 #include <string> 13 #include <set> 14 #include <utility> 15 #include <queue> 16 #include <stack> 17 #include <list> 18 #include <vector> 19 #include <cstdio> 20 #include <cstdlib> 21 #include <cstring> 22 #include <cmath> 23 #include <ctime> 24 #include <ctype.h> 25 using namespace std; 26 27 #define MAXN 110 28 29 int map[MAXN][MAXN]; 30 int vst[MAXN]; 31 int path[MAXN]; 32 int n; 33 int p; 34 int minnum,maxnum,midnum; 35 36 bool dfs(int v) 37 { 38 for(int i=0;i<n;i++) 39 if(map[v][i]>=p&&map[v][i]<=p+midnum&&!vst[i]) 40 { 41 vst[i]=1; 42 if(path[i]==-1||dfs(path[i])) 43 { 44 path[i]=v; 45 return true; 46 } 47 } 48 return false; 49 } 50 51 bool hungary() 52 { 53 memset(path,-1,sizeof(path)); 54 for(int i=0;i<n;i++) 55 { 56 memset(vst,0,sizeof(vst)); 57 if(!dfs(i)) //一旦發(fā)現(xiàn)有橫坐標(biāo)沒有對應(yīng)的y坐標(biāo)與其匹配就return false 58 return false; 59 } 60 return true; //表示所有的橫坐標(biāo)已經(jīng)全部匹配,return true 61 } 62 63 int main() 64 { 65 int t; 66 int i,j; 67 scanf("%d",&t); 68 while(t--) 69 { 70 int gmax=0,gmin=101; 71 scanf("%d",&n); 72 for(i=0;i<n;i++) 73 for(j=0;j<n;j++) 74 { 75 scanf("%d",&map[i][j]); 76 gmax=gmax>map[i][j]?gmax:map[i][j]; 77 gmin=gmin<map[i][j]?gmin:map[i][j]; 78 } 79 maxnum=gmax-gmin; 80 minnum=0; 81 while(1) 82 { 83 bool flag=false; 84 midnum=(maxnum+minnum)/2; 85 for(p=gmin;p+midnum<=gmax;p++) 86 { 87 if(hungary()) 88 { 89 flag=true; 90 break; 91 } 92 } 93 if(flag) 94 maxnum=midnum; 95 if(midnum==minnum) //注意:這三個if的順序不能隨意顛倒 96 break; 97 if(!flag) 98 minnum=midnum; 99 } 100 printf("%d\n",maxnum); 101 } 102 return 0; 103 }?
轉(zhuǎn)載于:https://www.cnblogs.com/XBWer/archive/2012/08/14/2638207.html
總結(jié)
以上是生活随笔為你收集整理的HDOJ---2236 无题II[二分枚举+匈牙利]的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IOS开发UI篇之──自定义加载等待框(
- 下一篇: HDU 1203 I NEED A OF