点击打开链接
题意:这题的题意隐晦的可以,中间不说了直接说求什么,求的是你画一张照片,照片有n个元素,1到n每个出现一次,问你对于上面的m张照片,如何分配你画的1到n使得题目中的式子的值最小,解释第二组样例应该就行了我们画的照片就可以是1 4 2 5 7 9 3 8 6没错就是第一行元素,那么对于第一列来说值是9,第二列的值是7,到第9列分别为9 7 7 1 4 11 4 8 7,那么最后值为58,求得就是这个最小的值
思路:对于每一列我可以选择的是1到n,那么就可以分别处理出1到n的话这个差值,然后我们不难发现这就是最小费用流,也可以理解为最小权匹配,所以看了大家的做法都是KM,我写的费用流都一样,建图的话应该很好建,模型还是挺简单的,看代码应该就可以看懂
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=2010;
typedef pair P;
struct edge{
int to,cap,rev,cost;
edge();
edge(int a,int b,int c,int d){to=a,cap=b,cost=c,rev=d;};
};
vectorG[maxn];
int h[maxn],dis[maxn];
int prevv[maxn],preve[maxn];
void add_edge(int st,int en,int cap,int cost){
G[st].push_back(edge(en,cap,cost,G[en].size()));
G[en].push_back(edge(st,0,-cost,G[st].size()-1));
}
int min_cost_flow(int st,int en,int f){
int ans=0;
memset(h,0,sizeof(h));
while(f>0){
priority_queue,greater
>que;
for(int i=0;i0&&dis[e.to]>dis[v]+e.cost+h[v]-h[e.to]){
dis[e.to]=dis[v]+e.cost+h[v]-h[e.to];
prevv[e.to]=v;
preve[e.to]=i;
que.push(P(dis[e.to],e.to));
}
}
}
if(dis[en]==inf) return -1;
for(int i=0;i
KM的话也是直接模版,权值变负求最大权,然后结果再变正就行了 PS:这道题目的难点好像是读懂题目把~~~~
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=210;
int s[maxn][maxn],visx[maxn],visy[maxn],match[maxn],num[maxn][maxn];
int lx[maxn],ly[maxn],tmp[maxn][maxn];
int n,m;
int hungarian(int x){
visx[x]=1;
for(int i=1;i<=m;i++){
if(!visy[i]&&lx[x]+ly[i]==s[x][i]){
visy[i]=1;
if(!match[i]||hungarian(match[i])){
match[i]=x;
return 1;
}
}
}
return 0;
}
int KM(){
int sum=0;
memset(lx,0,sizeof(lx));
memset(ly,0,sizeof(ly));
memset(match,0,sizeof(match));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
lx[i]=max(lx[i],s[i][j]);
for(int i=1;i<=n;i++){
while(1){
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
if(hungarian(i))break;
else{
int temp=INF;
for(int j=1;j<=n;j++){
if(visx[j]){
for(int k=1;k<=m;k++)
if(!visy[k])
temp=min(temp,lx[j]+ly[k]-s[j][k]);
}
}
if(temp==INF) return -1;
for(int j=1;j<=n;j++) if(visx[j]) lx[j]-=temp;
for(int j=1;j<=m;j++) if(visy[j]) ly[j]+=temp;
}
}
}
for(int i=1;i<=m;i++){
if(match[i]!=0){
if(s[match[i]][i]!=-INF) sum+=s[match[i]][i];
else return -1;
}
}
return sum;
}
int main(){
int T,cas=1,n1,m1;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n1,&m1);
n=m=n1;
for(int i=1;i<=m1;i++)
for(int j=1;j<=n1;j++)
scanf("%d",&num[i][j]);
for(int i=1;i<=n1;i++){
for(int j=1;j<=n1;j++){
int sum=0;
for(int k=1;k<=m1;k++) sum+=abs(num[k][j]-i);
tmp[j][i]=sum;
}
}
for(int i=1;i<=n1;i++){
for(int j=1;j<=n1;j++){
s[i][j]=-tmp[j][i];
}
}
int ans=KM();
printf("Case #%d: %d\n",cas++,-ans);
}
return 0;
}