• Nowcodercontest5278 L动物森友会(网络流)


    Nowcodercontest5278 L动物森友会(网络流)

    只有7天,是不是可以直接贪心啊。。。

    网络流做法:

    二分答案天数为\(mid\)

    建图:

    源点向\(Day1-Day7\)连边,第\(i\)天的流量上限是\((\lfloor \frac{mid}{7} \rfloor +[mid \mod 7 \ge i]) \cdot e\)

    对于所有\(a_{i,j}\)让,\(Day_{a_{i,j}}\)\(Task_i\)连上限为\(\infin\)的边

    每个\(Task_i\)向汇点连容量为\(c_i\)

    二分\(mid\)之后,判断是否满流\(=\sum c_i\)即可

    
    const int N=2e3+10,M=7*N,INF=1e9+10;
    
    int n,m,S,T,vc;
    
    //以下是网络流模板
    struct Edge{
    	int to,nxt,w;
    }e[M<<1];
    int head[N],ecnt;
    void AddEdge(int u,int v,int w) {
    	e[ecnt]=(Edge){v,head[u],w};
    	head[u]=ecnt++;
    }
    void Link(int u,int v,int w){ AddEdge(u,v,w),AddEdge(v,u,0); }
    #define erep(u,i) for(int i=head[u];~i;i=e[i].nxt)
    
    int dis[N];
    int Bfs(){
    	static queue <int> que;
    	rep(i,1,vc) dis[i]=INF;
    	que.push(S),dis[S]=0;
    	while(!que.empty()) {
    		int u=que.front(); que.pop();
    		erep(u,i) {
    			int v=e[i].to,w=e[i].w;
    			if(!w || dis[v]<=dis[u]+1) continue;
    			dis[v]=dis[u]+1,que.push(v);
    		}
    	}
    	return dis[T]<INF;
    }
    
    int Dfs(int u,int flowin) {
    	if(u==T) return flowin;
    	int flowout=0;
    	erep(u,i) {
    		int v=e[i].to,w=e[i].w;
    		if(dis[v]!=dis[u]+1 || !w) continue;
    		int t=Dfs(v,min(flowin-flowout,w));
    		flowout+=t,e[i].w-=t,e[i^1].w+=t;
    		if(flowin==flowout) break;
    	}
    	if(!flowout) dis[u]=0;
    	return flowout;
    }
    
    int Dinic(){
    	int ans=0;
    	while(Bfs()) ans+=Dfs(S,INF);
    	return ans;
    }
    
    int a[N][8],c[N],sum;
    
    int Check(int mid) {
    	if(m*mid<sum) return 0;
    	rep(i,1,n+10) head[i]=-1; ecnt=vc=0;
    	S=++vc,T=++vc;
    	rep(i,1,7) Link(S,++vc,(mid/7+(mid%7>=i))*m);
    	rep(i,1,n) {
    		vc++;
    		Link(vc,T,c[i]);
    		rep(j,1,7) if(a[i][j]) Link(j+2,vc,INF);
    	}
    	return Dinic()==sum;
    }
    
    
    int main(){
    	n=rd(),m=rd();
    	rep(i,1,n) {
    		c[i]=rd(),sum+=c[i];
    		rep(j,1,rd()) a[i][rd()]=1;
    	}
        // 二分答案,注意上界设定,防止边权爆int
    	int l=0,r=1e9/m,res;
    	while(l<=r) {
    		int mid=(l+r)>>1;
    		if(Check(mid)) r=mid-1,res=mid;
    		else l=mid+1;
    	}
    	printf("%d\n",res);
    }
    
    
    
    
  • 相关阅读:
    10106 Product
    枚举值不占对象空间
    编译器会强制没有数据成员的对象长度非零
    对象切片与虚函数机制
    私有继承成员的公有化
    2013年开发者需要了解的开发趋势和技能
    redis 入门笔记
    Tomcat的异步通讯配置使用NIO
    如何成为“10倍效率的开发者”
    如何安装Node.js
  • 原文地址:https://www.cnblogs.com/chasedeath/p/12727548.html
Copyright © 2020-2023  润新知