Joj 2662: procurement plan (two answers + multiple matches)
CCST @ jlu will hold this program design competition. In order to save money, you have to carefully consider all aspects, and the venue layout is no exception. When you deploy the site, you need to provide power for each computer. Because the computer and power supply are fixed, you need to purchase power cables to connect the computer and power supply. Kkk found that purchasing the same number of equal-length power cords is much cheaper than purchasing power cords with different lengths (although the price of the power cords is proportional to the length, it does not affect this rule :)), therefore, KKK decides to purchase power cables of the same length for site layout. Kkk wants to save money. Can you help him?
Question: bipartite answer + Multi-match, enumeration answer, add an edge smaller than or equal to the enumeration number to the network to see if it is feasible. If it is feasible, continue to find a solution smaller than it, if not, find a larger solution.
The diagram of the Multi-match stream. You can change the weight of the connected edge between a point that can match multiple words to the number of matching times.
#include <cstdio>#include <cstring>#define max(a,b) (a>b?a:b)#define min(a,b) (a<b?a:b)const int maxn=800;const int inf = 1<<28;const int s=0 ;struct Edge { int v,next,w;}edge[maxn*maxn];int head[maxn],cnt;//for sapvoid addedge(int u , int v , int w){ edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].v=u; edge[cnt].w=0; edge[cnt].next=head[v]; head[v]=cnt++;}int n,m,cc;///int sap(int t){ int pre[maxn],cur[maxn]; int dis[maxn],gap[maxn]; int flow=0 , aug=inf ,u; bool flag; for (int i=0 ; i<=t ; ++i) { cur[i]=head[i]; gap[i]=dis[i]=0; } gap[s]=t+1; u=pre[s]=s; while (dis[s]<=t) { flag=0 ; for (int &j=cur[u] ; ~j ; j=edge[j].next) { int v=edge[j].v; if (edge[j].w>0 && dis[u]==dis[v]+1) { flag=1; if(edge[j].w<aug)aug=edge[j].w; pre[v]=u; u=v; if (u==t) { flow+=aug; while (u!=s) { u=pre[u]; edge[cur[u]].w-=aug; edge[cur[u]^1].w+=aug; } aug=inf; } break; } } if (flag)continue ; int mindis=t+1; for (int j=head[u]; ~j ; j=edge[j].next) { int v=edge[j].v; if (edge[j].w>0 && dis[v]<mindis) { mindis=dis[v]; cur[u]=j; } } if(--gap[dis[u]]==0)break; gap[dis[u]=mindis+1]++; u=pre[u]; } return flow;}int map[maxn][maxn];int c[maxn];int main (){ int cas; scanf("%d",&cas); while (cas--) { scanf("%d%d%d",&n,&m,&cc); for (int i=0 ; i<n ; ++i) { for (int j=0 ; j<m ; ++j) { scanf("%d",map[i]+j); } } int sum=0; for (int i=0 ; i<m ; ++i) { scanf("%d",c+i); sum+=c[i]; } if(sum<n){puts("-1"); continue;} int ans=inf; int l=0,r=10000; /// while (l<=r) { int mid=(l+r)>>1; memset (head , -1 , sizeof(head)); cnt=0; for (int i=0 ; i<n ; ++i) { addedge (0 , i+1 , 1); for (int j=0 ; j<m ; ++j) { if(map[i][j]<=mid) { addedge(i+1,j+n+1,1); } } } for (int j=0 ; j<m ; ++j) addedge(j+n+1 , n+m+1 , c[j]); int match; match=sap(n+m+1); //printf("match = %d\n",match); if(n==match) { r=mid-1; ans=min(ans,mid); } else l=mid+1; } printf("%d\n",ans*cc*n); } return 0;}