传送门
可以把原图看做一个二分图,人在左边,任务在右边,求一个带权的最大和最小完美匹配
然而我并不会二分图做法,所以只好直接用费用流套进去,求一个最小费用最大流和最大费用最大流即可
1 //minamoto 2 #include3 #include 4 #include 5 #include 6 #define inf 0x3f3f3f3f 7 using namespace std; 8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 9 char buf[1<<21],*p1=buf,*p2=buf; 10 inline int read(){ 11 #define num ch-'0' 12 char ch;bool flag=0;int res; 13 while(!isdigit(ch=getc())) 14 (ch=='-')&&(flag=true); 15 for(res=num;isdigit(ch=getc());res=res*10+num); 16 (flag)&&(res=-res); 17 #undef num 18 return res; 19 } 20 const int N=205,M=25005; 21 int ver[M],Next[M],head[N],edge[M],flow[M],tot=1; 22 int dis[N],disf[N],n,s,t,ans,Pre[N],last[N],vis[N],x; 23 queue<int> q; 24 inline void add(int u,int v,int e,int f){ 25 ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e,flow[tot]=f; 26 ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=-e,flow[tot]=0; 27 } 28 bool spfa_min(){ 29 memset(dis,0x3f,sizeof(dis)); 30 memset(vis,0,sizeof(vis)); 31 memset(disf,0x3f,sizeof(disf)); 32 q.push(s),dis[s]=0,vis[s]=1,Pre[t]=-1; 33 while(!q.empty()){ 34 int u=q.front();q.pop();vis[u]=0; 35 for(int i=head[u];i;i=Next[i]){ 36 int v=ver[i]; 37 if(flow[i]>0&&dis[v]>dis[u]+edge[i]){ 38 dis[v]=dis[u]+edge[i],Pre[v]=u; 39 last[v]=i,disf[v]=min(disf[u],flow[i]); 40 if(!vis[v]) vis[v]=1,q.push(v); 41 } 42 } 43 } 44 return Pre[t]!=-1; 45 } 46 int dinic_min(){ 47 int maxflow=0,mincost=0; 48 while(spfa_min()){ 49 int u=t; 50 maxflow+=disf[t],mincost+=disf[t]*dis[t]; 51 while(u!=s){ 52 flow[last[u]]-=disf[t]; 53 flow[last[u]^1]+=disf[t]; 54 u=Pre[u]; 55 } 56 } 57 return mincost; 58 } 59 bool spfa_max(){ 60 memset(dis,0xef,sizeof(dis)); 61 memset(vis,0,sizeof(vis)); 62 memset(disf,0x3f,sizeof(disf)); 63 q.push(s),dis[s]=0,vis[s]=1,Pre[t]=-1; 64 while(!q.empty()){ 65 int u=q.front();q.pop();vis[u]=0; 66 for(int i=head[u];i;i=Next[i]){ 67 int v=ver[i]; 68 if(flow[i]>0&&dis[v] edge[i]){ 69 dis[v]=dis[u]+edge[i],Pre[v]=u; 70 last[v]=i,disf[v]=min(disf[u],flow[i]); 71 if(!vis[v]) vis[v]=1,q.push(v); 72 } 73 } 74 } 75 return Pre[t]!=-1; 76 } 77 int dinic_max(){ 78 int maxflow=0,maxcost=0; 79 while(spfa_max()){ 80 int u=t; 81 maxflow+=disf[t],maxcost+=disf[t]*dis[t]; 82 while(u!=s){ 83 flow[last[u]]-=disf[t]; 84 flow[last[u]^1]+=disf[t]; 85 u=Pre[u]; 86 } 87 } 88 return maxcost; 89 } 90 int main(){ 91 n=read(); 92 for(int i=1;i<=n;++i) 93 for(int j=1;j<=n;++j) 94 x=read(),add(i,j+n,x,1); 95 s=0,t=n+n+1; 96 for(int i=1;i<=n;++i) add(s,i,0,1),add(i+n,t,0,1); 97 printf("%d\n",dinic_min()); 98 for(int i=2;i<=tot;i+=2) flow[i]+=flow[i^1],flow[i^1]=0; 99 printf("%d\n",dinic_max()); 100 return 0; 101 }