http://acm.timus.ru/problem.aspx?space=1&num=1076
图论题 关键在于建图 然后就是对模版的熟练运用
KM 最大匹配 此题是求最小匹配 只要把值变成负的 最后把结果再取一次负 就可以了
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<vector> #include<stack> #include<set> #include<map> #include<queue> #include<algorithm> #include<cmath> #define LL long long using namespace std; const int N=155; const int INF=0x3f3f3f3f; //typedef pair<int,int>point; int c[N][N]; int sum[N]; int dist[N][N]; int f[N]; bool lv[N],rv[N]; int a[N],b[N]; bool dfs(int x,int n) { lv[x]=true; for(int i=1;i<=n;++i) { if(!rv[i]&&a[x]+b[i]==dist[x][i]) { rv[i]=true; if(f[i]==-1||dfs(f[i],n)) { f[i]=x; return true; } } } return false; } int Km(int n) { memset(f,-1,sizeof(f)); memset(b,0,sizeof(b)); for(int i=1;i<=n;++i) { a[i]=-INF; for(int j=1;j<=n;++j) a[i]=max(a[i],dist[i][j]); } for(int l=1;l<=n;++l) { while(true) { memset(lv,false,sizeof(lv)); memset(rv,false,sizeof(rv)); if(dfs(l,n)) break; int d=INF; for(int i=1;i<=n;++i) { if(lv[i]) for(int j=1;j<=n;++j) { if(!rv[j]) d=min(d,a[i]+b[j]-dist[i][j]); } } for(int i=1;i<=n;++i) { if(lv[i]) a[i]-=d; if(rv[i]) b[i]+=d; } } } int ans=0; for(int i=1;i<=n;++i) { if(f[i]!=-1) ans+=dist[f[i]][i]; } return ans; } int main() { int n; while(cin>>n) { memset(sum,0,sizeof(sum)); for(int i=1;i<=n;++i) { for(int j=1;j<=n;++j) { cin>>c[i][j]; sum[j]+=c[i][j]; } } memset(dist,0,sizeof(dist)); for(int i=1;i<=n;++i) { for(int j=1;j<=n;++j) { int tmp=sum[j]-c[i][j]; dist[j][i]=-tmp; } } cout<<(-Km(n))<<endl; } return 0; }