P3529 [POI 2011] PRO-Programming Contest
P3529\(\mathbf{} \begin{Bmatrix} \frac{{\Large LUOGU-P3529} }{{\color{Red}\Large Solution} }\mathbf{} {No.3} \end{Bmatrix}\times{}\) NeeDna
P3529 [POI 2011] PRO-Programming Contest解题报告
题目分析:
有 \(n\) 个人 \(m\) 个任务,每个人完成一道题用 \(r\) 时,比赛时间为 \(t\) ,有 \(k\) 对完成人物的关系。要在规定时间 \(t\) 内,在解题最多的情况下,罚时最少。
为了使罚时最少,我们会让题目尽量在前面跑,而且一个人跑的次数小于等于 $\left \lfloor \frac{t}{r} \right \rfloor $ ,所以可以用二分图匹配完成。
具体做法:
跑 $\left \lfloor \frac{t}{r} \right \rfloor $ 次二分图最大匹配,保证一个人最多做 $\left \lfloor \frac{t}{r} \right \rfloor $ 道题,并且由于二分图匹配每个人都进行了多次,使得一个人不会做太多道题。不仅如此,二分图最大匹配还保证了解题数最多,所以叫为完美的解决了这道题目。
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int n,m,vis[N],ma[N],ans=0,r,t,k,ans1,ans2,ti[N];
vector<int> ve[N];
int dfs(int x){//二分图最大匹配模板 不解释
for(int v:ve[x]){
if(vis[v]) continue;
vis[v]=1;
if(!ma[v]||dfs(ma[v])){
ma[v]=x;
return 1;
}
}
return 0;
}
int main(){
cin>>n>>m>>r>>t>>k;//直接抄不会过
for(int i=1,x,y;i<=k;i++){
cin>>x>>y;ve[x].emplace_back(y);//人连题
}
for(int i=1,flg=0;i*r<=t;i++){//跑t/r遍最大匹配
for(int j=1;j<=n;j++){
memset(vis,0,sizeof(vis));
if (dfs(j)){
ans1++;
ans2+=i*r;
flg=1;
}
}if(!flg||ans1>=m) break;//剪枝
}
cout<<ans1<<" "<<ans2<<'\n';
for(int i=1;i<=m;i++){
if(ma[i])cout<<ma[i]<<" "<<i<<" "<<(ti[ma[i]]++)*r<<'\n';//时间分配
}
return 0;
}

浙公网安备 33010602011771号