題面: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(網絡流複雜度)
代碼:c++
#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\n",ans1,ans2); F(i,1,sum)printf("%d %d %d\n",ma[i].x,ma[i].y,ma[i].s); return 0; }