hdu 2255 奔小康赚大钱 最大权匹配KM

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255

传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子。
这可是一件大事,关系到人民的住房问题啊。村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子。
另一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出20万.(当然是在他们的经济范围内).现在这个问题就是村领导怎样分配房子才能使收入最大.(村民即使有钱购买一间房子但不一定能买到,要看村领导分配的).
 
题意描述:由于此题为中文题,这里不作翻译。
算法分析:最大权匹配问题,KM算法的入门题。百度KM算法有很多相关介绍的,这里不再累述。说明一点,KM优化:slack数组保存的是在dfs找增广路的时候随便求出Y集(二分图:X集和Y集)中不在相等子图中的每个y的值min(lx[x]-ly[y]-w[x][y]),最终算法复杂度为O(n^3)。
对编译知识不是很了解,为什么这道题G++提交TLE而C++提交AC,感觉很厉害很高级的样子。
 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<cstdlib>

 5 #include<cmath>

 6 #include<algorithm>

 7 #include<vector>

 8 #include<queue>

 9 #define inf 0x7fffffff

10 using namespace std;

11 const int maxn=300+10;

12 

13 int n,nx,ny;

14 int lx[maxn],ly[maxn],visx[maxn],visy[maxn];

15 int link[maxn],slack[maxn];

16 int w[maxn][maxn];

17 

18 int dfs(int x)

19 {

20     visx[x]=1;

21     for (int y=1 ;y<=ny ;y++)

22     {

23         if (visy[y]) continue;

24         int t=lx[x]+ly[y]-w[x][y];

25         if (t==0)

26         {

27             visy[y]=1;

28             if (link[y]==-1 || dfs(link[y]))

29             {

30                 link[y]=x;

31                 return 1;

32             }

33         }

34         else if (slack[y]>t) slack[y]=t;

35     }

36     return 0;

37 }

38 

39 int KM()

40 {

41     memset(ly,0,sizeof(ly));

42     memset(link,-1,sizeof(link));

43     for (int x=1 ;x<=nx ;x++)

44     {

45         lx[x]=-inf;

46         for (int y=1 ;y<=ny ;y++)

47             lx[x]=max(lx[x],w[x][y]);

48     }

49     for (int x=1 ;x<=nx ;x++)

50     {

51         for (int j=1 ;j<=ny ;j++) slack[j]=inf;

52         while (1)

53         {

54             memset(visx,0,sizeof(visx));

55             memset(visy,0,sizeof(visy));

56             if (dfs(x)) break;

57             int d=inf;

58             for (int j=1 ;j<=ny ;j++)

59             {

60                 if (!visy[j] && slack[j]<d)

61                     d=slack[j];

62             }

63             for (int i=1 ;i<=nx ;i++)

64                 if (visx[i]) lx[i] -= d;

65             for (int i=1 ;i<=ny ;i++)

66             {

67                 if (visy[i]) ly[i] += d;

68                 else slack[i] -= d;

69             }

70         }

71     }

72     int ans=0;

73     for (int i=1 ;i<=ny ;i++)

74         if (link[i]!=-1) ans += w[link[i] ][i];

75     return ans;

76 }

77 

78 int main()

79 {

80     while (scanf("%d",&n)!=EOF)

81     {

82         nx=ny=n;

83         for (int i=1 ;i<=n ;i++)

84         {

85             for (int j=1 ;j<=n ;j++)

86                 scanf("%d",&w[i][j]);

87         }

88         printf("%d\n",KM());

89     }

90     return 0;

91 }

 

你可能感兴趣的:(HDU)