HDU 2255 奔小康发大财
Solution:
KM算法
关于KM算法有一篇极好的文档http://www.cse.ust.hk/~golin/COMP572/Notes/Matching.pdf
Implementation:
#include <cstdio> #include <algorithm> #include <cstring> #include <climits> using namespace std; const int N(305); int w[N][N]; int Lx[N], Ly[N], slack[N]; bool S[N], T[N]; int match[N]; int n; bool dfs(int u) { S[u]=true; for(int v=1; v<=n; v++) { if(T[v]) { continue; } int tmp=Lx[u]+Ly[v]-w[u][v]; if(tmp==0) { T[v]=true; if(!match[v] || dfs(match[v])) { match[v]=u; return true; } } else { slack[v]=min(slack[v], tmp); } } return false; } void KM() { memset(match, 0, sizeof(match)); memset(Lx, 0x3f, sizeof(Lx)); memset(Ly, 0x3f, sizeof(Ly)); for(int i=1; i<=n; i++) //phase { for(int i=1; i<=n; i++) { slack[i]=INT_MAX; //error-prone } for(int a; ;) { memset(S, 0, sizeof(S)); memset(T, 0, sizeof(T)); if(dfs(i)) break; a=INT_MAX; for(int j=1; j<=n; j++) { if(!T[j]) { a=min(a, slack[j]); } } for(int j=1; j<=n; j++) { if(S[j]) { Lx[j]-=a; } if(T[j]) { Ly[j]+=a; } else { slack[j]-=a; } } } } int res=0; for(int i=1; i<=n; i++) { res+=w[match[i]][i]; } printf("%d\n", res); } int main() { for(; ~scanf("%d", &n); ) { for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { scanf("%d", w[i]+j); } } KM(); } }
Error-prone:
我把Lx, Ly, slack都初始化成0x3f3f3f3f,导致dfs中
slack[v]=min(slack[v], tmp);
失灵。