hdu 2426 Interesting Housing Problemの最も大きな権利はKMアルゴリズムにマッチします。

16198 ワード

テーマリンク:http://acm.hdu.edu.cn/showproblem.php?pid=2426
For any school,it is hard to find a feasible accomodation plan with everstudent asigned to a suitable apple appment while keeping everone happy,let alone an optimal one.Recently the president of University ABC,Peterson,Petersonウィhile Peterson dot like the delegating the tassk directly to the clasadvisorss s as as as mamamashshshshhos arararararararaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaNevertheless、Peterson does not know how this task could be accocococococococompplished、so he asks you to solive this so-caled“interesting”problem for him.
Suppose that there re re N students and M rooms.Each student is asked to rate some rooms(not necessarly all M rooms)by stating how he/she likes the room.The rating can be represented astors the intement the stindersor negative implaying that the student does not like living in the room.Note that you can never assign a student to a room which he/she has not rated、as the absence of rating indicates the student the student cant.cant.cant.cant.cant.cant.cant.cant。
With limited information available,you've decided to simply find an assignment such that everent is assigned to a room he/she has rated,no two student s the same room,and the sum of rating Themizings。
 
学校にはn人の学生とm人のアパートの部屋がありますが、学生一人はいくつかの部屋に点数をつけています。点数が正しければ、学生はこの部屋が好きだと説明しています。0なら、この部屋に中立的で、負なら、この部屋が嫌いです。学生は好きではない部屋と採点のない部屋に住まないです。このn人の学生を手配して最大の点数を求めにきます。
アルゴリズム解析:KMアルゴリズム。n人の学生はX集として、m部屋をY集として、KMアルゴリズムを呼出してもいいです。
  1 #include<iostream>

  2 #include<cstdio>

  3 #include<cstring>

  4 #include<cstdlib>

  5 #include<cmath>

  6 #include<algorithm>

  7 #define inf 0x7fffffff

  8 using namespace std;

  9 const int maxn=500+10;

 10 

 11 int n,m;

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

 13 int link[maxn],slack[maxn],w[maxn][maxn];

 14 

 15 int dfs(int x)

 16 {

 17     visx[x]=1;

 18     for (int y=1 ;y<=m ;y++) if (w[x][y]!=-1)

 19     {

 20         if (visy[y]) continue;

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

 22         if (t==0)

 23         {

 24             visy[y]=1;

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

 26             {

 27                 link[y]=x;

 28                 return 1;

 29             }

 30         }

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

 32     }

 33     return 0;

 34 }

 35 

 36 int KM()

 37 {

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

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

 40     for (int x=1 ;x<=n ;x++)

 41     {

 42         lx[x]=-inf;

 43         for (int y=1 ;y<=m ;y++)

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

 45     }

 46     for (int x=1 ;x<=n ;x++)

 47     {

 48         for (int i=1 ;i<=m ;i++) slack[i]=inf;

 49         int flag=0;

 50         for (int i=1 ;i<=m ;i++) if (w[x][i]!=-1) flag=1;

 51         while (flag)

 52         {

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

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

 55             if (dfs(x)) break;

 56             int d=inf;

 57             for (int i=1 ;i<=m ;i++)

 58                 if (!visy[i] && d>slack[i]) d=slack[i];

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

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

 61             for (int i=1 ;i<=m ;i++)

 62             {

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

 64                 else slack[i] -= d;

 65             }

 66         }

 67     }

 68     int ans=0;

 69     int vis[maxn];

 70     memset(vis,0,sizeof(vis));

 71     for (int i=1 ;i<=m ;i++)

 72     {

 73         if (link[i]!=-1)

 74         {

 75             ans += w[link[i] ][i];

 76             vis[link[i] ]=1;

 77         }

 78     }

 79     int i=1;

 80     for (i=1 ;i<=n ;i++)

 81         if (vis[i]==0) return -1;

 82     return ans;

 83 }

 84 

 85 int main()

 86 {

 87     int e;

 88     int ncase=1;

 89     while (scanf("%d%d%d",&n,&m,&e)!=EOF)

 90     {

 91         memset(w,-1,sizeof(w));

 92         int a,b,c;

 93         for (int i=0 ;i<e ;i++)

 94         {

 95             scanf("%d%d%d",&a,&b,&c);

 96             a++ ;b++ ;

 97             if (c>=0) w[a][b]=c;

 98         }

 99         printf("Case %d: %d
",ncase++,KM()); 100 } 101 return 0; 102 }