zoukankan      html  css  js  c++  java
  • P3529 [POI2011]PRO-Programming Contest

    题面:https://www.luogu.com.cn/problem/P3529
    题意:(n)个人(m)个题目,每个题要(r)分钟完成。比赛有(t)分钟。
    给出每个人会做哪些题目,请你安排一个每个人在什么时候做什么题目,
    使得做出来的题目数最多。在做题数一样多的情况下,罚时尽量小。
    罚时为(sum) 每道题做出来的时间
    (1(le)n,m (le) 500,1 (le) r,t (le) 1e6)
    题解:n,m都不大,考虑使用网络流。
    可以看出,此题是二分图匹配模型,那就按套路来做:
    (S) (Rightarrow) 每个人,(v=r/t);
    每个人 (Rightarrow) 每道题,(v=1);
    每道题 (Rightarrow) (T)(v=1)
    但这样的话,我们只能保证做题数最大,罚时不一定最少。
    为什么呢?这就好像我和cjy大佬一起去打ACM,因为我太菜了,啥都不会做,
    大佬不仅做了他能做的高难度题,可能还会抢了我的题,从而造成罚时更多。
    那这个问题如何解决呢?既然我们希望更多人参与进来,我们可以每次从
    源点(S)向每个人释放1个流量,这样就避免了抢题的情况。当最大流不再
    增加时,程序结束。
    时间复杂度:O(网络流复杂度)
    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define re register int
    #define F(x,y,z) for(re x=y;x<=z;x++)
    #define FOR(x,y,z) for(re x=y;x>=z;x--)
    typedef long long ll;
    #define I inline void
    #define IN inline int
    #define C(x,y) memset(x,y,sizeof(x))
    #define STS system("pause")
    template<class U>I read(U &res){
    	res=0;register U g=1;register char ch=getchar();
    	while(!isdigit(ch)){
    		if(ch=='-')g=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch)){
    		res=(res<<3)+(res<<1)+(ch^48);
    		ch=getchar();
    	}
    	res*=g;
    }
    const int INF=1e9+7;
    struct E{
    	int to,nt,w;
    }e[303000];
    #define T e[k].to
    struct Match{
    	int x,y,s;
    }ma[2020];
    int n,m,S,D,r,t,p,M,cur[202000],tot=-1,sum,dis[202000],vis[202000],X[202000],Y[202000],head[202000],las,ans1,ans2,now;
    I add(int x,int y,int w){
    	//cout<<"!"<<x<<" "<<y<<" "<<w<<endl;
    	e[++tot].to=y;
    	e[tot].nt=head[x];
    	head[x]=tot;
    	e[tot].w=1;
    	e[++tot].to=x;
    	e[tot].nt=head[y];
    	head[y]=tot;
    	e[tot].w=0;
    }
    IN D_1(int x,int lim){
    //	cout<<"!"<<x<<" "<<lim<<endl;
    	if(x==D||!lim)return lim;
    	re flow=0,ext;
    	for(re k=head[x];k!=-1;k=e[k].nt){
    		if(dis[x]+1==dis[T]&&e[k].w>0){
    			ext=D_1(T,min(lim,e[k].w));
    			if(!ext)continue;
    			flow+=ext;lim-=ext;
    			e[k].w-=ext;e[k^1].w+=ext;
    			if(!lim)break;
    		}
    	}
    	if(lim)dis[x]=-1;
    	//cout<<x<<" "<<flow<<endl;
    	return flow;
    }
    queue<int>q;
    IN B_1(){
    	C(dis,-1);
    	dis[S]=0;
    	q.push(S);
    	memcpy(cur,head,sizeof(head));
    	while(!q.empty()){
    		p=q.front();q.pop();
    		for(re k=head[p];k!=-1;k=e[k].nt){
    			if(dis[T]==-1&&e[k].w>0){
    				//cout<<"@"<<p<<" "<<T<<" "<<k<<" "<<e[k].w<<endl;
    				dis[T]=dis[p]+1;
    				q.push(T);
    			}
    		}
    	}
    	return dis[D]!=-1;
    }
    I dinic(int _t){
    	re dt;
    	while(B_1()){dt=D_1(S,INF);ans1+=dt;ans2+=dt*_t;}
    }
    I get_match(int _t){
    	for(re k=0;k<=((M-1)<<1);k+=2){
    		if((!vis[T-n])&&(!e[k].w)){
    			sum++;
    			ma[sum].x=e[k^1].to;
    			ma[sum].y=T-n;
    			ma[sum].s=_t;
    			vis[T-n]=1;
    		}
    	}
    }
    int main(){
    	read(n);read(m);read(r);read(t);read(M);
    	C(head,-1);tot=-1;S=0;D=n+m+1;C(vis,0);
    	F(i,1,M){read(X[i]);read(Y[i]);add(X[i],n+Y[i],1);}
    	F(i,1,m)add(n+i,D,1);
    	now=r;las=ans1=ans2=sum=0;
    	while(now<=t){
    		//STS;
    		F(i,1,n)add(S,i,1);
    		dinic(now);
    		if(ans1==las)break;
    		las=ans1;
    		get_match(now-r);
    		now+=r;		
    	}	
    	printf("%d %d
    ",ans1,ans2);
    	F(i,1,sum)printf("%d %d %d
    ",ma[i].x,ma[i].y,ma[i].s);	
    	return 0;
    }
    
  • 相关阅读:
    Taxes
    Tennis Championship
    Urbanization
    字符串的匹配
    Alyona and a tree
    Alyona and mex
    Alyona and flowers
    Alyona and copybooks
    Subordinates
    线程的暂停、恢复和终止
  • 原文地址:https://www.cnblogs.com/Purple-wzy/p/12099184.html
Copyright © 2011-2022 走看看