UVA 11324 The Largest Clique (拆点+KM)
2015-09-09 20:56
417 查看
题意:有n个盒子,围城一个环,每个盒子里可能有糖果或无糖果,总糖果不超过N,要求,把盒子中糖果数超过1的移到无糖果的盒子中,问最少几步。
分析:把有糖果数为val的盒子,拆成val个装一个糖果的盒子,编号num1从1开始累加,但他们在同一点。然后就是与每个盒子匹配,用km,这里要求最少几步,就拿距离来建图。
w[i][j] 表示第i个糖果的盒子,到第j个盒子的距离,由于是求最少,那么w[i][j]=-w[i][j],求出最大,然后答案取反就是最小。
分析:把有糖果数为val的盒子,拆成val个装一个糖果的盒子,编号num1从1开始累加,但他们在同一点。然后就是与每个盒子匹配,用km,这里要求最少几步,就拿距离来建图。
w[i][j] 表示第i个糖果的盒子,到第j个盒子的距离,由于是求最少,那么w[i][j]=-w[i][j],求出最大,然后答案取反就是最小。
#include <iostream> #include <stdio.h> #include <math.h> #include <algorithm> #include <queue> #include <stack> #include <vector> #include <string> #include <string.h> #include <map> #include <set> using namespace std; const int maxn=505; const int inff=1<<30; int w[maxn][maxn],n,m; int lx[maxn],ly[maxn]; int r[maxn],slack[maxn],val; bool s[maxn],t[maxn]; bool match(int i) { s[i]=true; for(int j=1;j<=m;j++) { int temp=lx[i]+ly[j]-w[i][j]; if(temp==0&&!t[j]) { t[j]=true; if(!r[j]||match(r[j])) { r[j]=i; return true; } } if(!t[j]) slack[j]=min(slack[j],temp); } return false; } void update() { int i,j; int a=inff; /* for(i=1;i<=n;i++) { if(s[i]) for(j=1;j<=m;j++) { if(!t[j]) { a=min(a,lx[i]+ly[j]-w[i][j]); } } }*/ for(j=1;j<=m;j++) if(!t[j]) a=min(a,slack[j]); for(i=1;i<=n;i++) { if(s[i])lx[i]-=a; } for(j=1;j<=m;j++) if(t[j])ly[j]+=a; } void km() { int i,j; memset(r,0,sizeof r); memset(lx,0,sizeof lx); memset(ly,0,sizeof ly); for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { lx[i]=max(lx[i],w[i][j]); } } for(i=1;i<=n;i++) { for( j=1;j<=m;j++) slack[j]=inff; while(1) { memset(s,0,sizeof s); memset(t,0,sizeof t); if(match(i))break; else update(); } } } int x[maxn],y[maxn]; int main() { int num1,num2; while(scanf("%d",&n)!=EOF) { /*****************************///拆点 num1=num2=1; for(int i=1;i<=n;i++) { scanf("%d",&val); if(val) { for(int j=1;j<=val;j++) x[num1++]=i; y[num2++]=i; } else y[num2++]=i; } for(int i=1;i<num1;i++) { for(int j=1;j<num2;j++) { w[i][j]=min(max(x[i],y[j])-min(x[i],y[j]),min(x[i],y[j])+n-max(x[i],y[j])); if(x[i]==y[j])w[i][j]=0; w[i][j]=-w[i][j]; } } /******************************/ n=num1-1,m=num2-1; km(); int ans=0; for(int j=1;j<=m;j++) { if(r[j]) { ans+=w[r[j]][j]; } } printf("%d\n",-ans); } return 0; }
相关文章推荐
- iOS—实现UI imageview的底层
- Expression Tree Build
- 09-09 Service(续)、UI主线程、AsyncTask(UI主线程)
- Android Service——在子线程中更新UI
- iOS小结(五) 结合 Instrument 分析并解决memory issues
- interview questions
- ios-UIKit 练习
- UINavigationController和UIBarButtonItem
- UIView
- Qt5 中使用了QQuickWidget,程序退出时容易崩溃的解决办法。
- button初始化类目
- Java- 字符串(String,StringBuffer,StringBuilder类)
- iOSInterviewQuestions/iOS面试问题
- UIImagePickerController
- UIAlertController
- queue POJ 2259 Team Queue
- hdu5014Number Sequence 位运算
- 2-LTE Identification I: UE and ME Identifiers
- UGUI Button控件
- Sequential Monte Carlo Methods