bzoj4950: [Wf2017]Mission Improbable
跟着靖靖做题%%%%%
这题一看就觉得和之前的某场模拟赛的一道题很像,找假如某行某列的最大值一样的就可以只堆一个,跑匈牙利就行
一开始以为箱子不能移动-_-!
然后有个坑,大家都知道当这个位置有箱子就偷剩一个,但是假如当前行当前列没有箱子,就算他们最大值一样也不能建边
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #define pd(a,b,c,d) a==b?c:d using namespace std; typedef long long LL; int n,m;LL c[110][110]; LL hmx[110],lmx[110]; void get_max() { for(int i=1;i<=n;i++) { hmx[i]=0; for(int j=1;j<=m;j++) hmx[i]=max(hmx[i],c[i][j]); } for(int j=1;j<=m;j++) { lmx[j]=0; for(int i=1;i<=n;i++) lmx[j]=max(lmx[j],c[i][j]); } } //----------init------------- struct node { int x,y,next; }a[11000];int len,last[110]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } void composition()//二分图匹配旨在解决某点同时作为hmx和lmx情况 { for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(hmx[i]==lmx[j]&&c[i][j]!=0)ins(i,j); } int tim,v[110]; int match[110]; bool findmuniu(int x) { for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(v[y]!=tim) { v[y]=tim; if(match[y]==0||findmuniu(match[y])==true) { match[y]=x; return true; } } } return false; } //----------match------------- int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%lld",&c[i][j]); get_max(); LL ans=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) ans+=pd(c[i][j],0,0,c[i][j]-1); for(int i=1;i<=n;i++)ans-=pd(hmx[i],0,0,hmx[i]-1); for(int j=1;j<=m;j++)ans-=pd(lmx[j],0,0,lmx[j]-1); composition(); memset(match,0,sizeof(match)); memset(v,0,sizeof(v));tim=0; for(int i=1;i<=n;i++) { tim++; if(findmuniu(i)==true)ans+=pd(hmx[i],0,0,hmx[i]-1); } printf("%lld\n",ans); return 0; }
pain and happy in the cruel world.