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;
}
posted @ 2025-05-30 20:30  NeeDna  阅读(14)  评论(0)    收藏  举报