zoukankan      html  css  js  c++  java
  • UVALive6571 It Can Be Arranged(最小路径覆盖)

    题意:现在有n个课程,每个课程有一定的参与人数,然后每个课程有开始时间和结束时间ai,bi.

    而且给定了一个矩阵clean(ij),表示的是上完i课程需要clean[i][j]的时间打扫卫生才能继续上j课程。也就是说如果上完i课程要上j课程就需要满足条件

    b[i]+clean[i][j]<a[j]. 然后每间课室能容纳一定的人数(如果课室30个人,课程有61个人的话,就需要三间教室),问最少要用多少间课室安排全部的课程。

    看完题后觉得是网络流,然后想了一下跟大白上讲得一道题很像,就是一个最小路径覆盖,不过这题是带权的。不停地回忆建图方法,但就是想不起来,后来找了师弟借了大白看了一下才想起建模的方法。

    对于每个课程i我们建两个点i和i'.如果上完i课程来得及上j课程的话,就i->j'.  然后源点向所以的i点连一条边,容量就是对应的需要开的课室数,然后所有i'点向汇点连边,对应的容量也是需要开的课室数。

    最后跑一次最大流,答案就是总的课室数-最大流。原因就是每一条流出去的边看成是重用了已有的课室,每一条流出去的边就相当于节省了多少间课室。过了题说明我的Dicnic模板还是可以用的,不过还是找时间补个SAP- -0

    #include <iostream>
    #include <cstring>
    #include <string>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <queue>
    #include <algorithm>
    #include <map>
    #include <vector>
    #include <string>
    using namespace std;
    
    #define maxn 300
    #define maxe 200000
    #define inf 0x3f3f3f3f
    
    struct Edge
    {
    	int u,v,cap;
    	int nxt;
    }edge[maxe];
    
    
    int head[maxn];
    int n,m;
    int a[maxn],b[maxn],s[maxn];
    int mat[maxn][maxn];
    
    
    struct Dicnic
    {
    	int level[maxn];
    	int iter[maxn];
    	int add;
    	void init()
    	{
    		add=0;memset(head,-1,sizeof(head));
    		memset(iter,-1,sizeof(iter));
    	}
    	void insert(int u,int v,int c)
    	{
    		edge[add].u=u;edge[add].v=v;
    		edge[add].cap=c;
    		edge[add].nxt=head[u];head[u]=add++;
    
    		edge[add].u=v;edge[add].v=u;
    		edge[add].cap=0;
    		edge[add].nxt=head[v];head[v]=add++;
    	}
    
    	void bfs(int s){
    		memset(level,-1,sizeof(level));
    		queue<int> que;
    		level[s]=0;
    		que.push(s);
    		while(!que.empty()){
    			int v=que.front();que.pop();
    			for(int i=head[v];i!=-1;i=edge[i].nxt){
    				Edge &e=edge[i];
    				if(e.cap>0&&level[e.v]<0){
    					level[e.v]=level[v]+1;
    					que.push(e.v);
    				}
    			}
    		}
    	}
    
    	int dfs(int v,int t,int f){
    		if(v==t) return f;
    		for(int &i=iter[v];i!=-1;i=edge[i].nxt){
    			Edge &e=edge[i];Edge &reve=edge[i^1];
    			if(e.cap>0&&level[v]<level[e.v]){
    				int d=dfs(e.v,t,min(f,e.cap));
    				if(d>0){
    					e.cap-=d;reve.cap+=d;
    					return d;
    				}
    			}
    		}
    		return 0;
    	}
    
    	int max_flow(int s,int t){
    		int flow=0;
    		for(;;){
    			bfs(s);
    			if(level[t]<0) return flow;
    			memcpy(iter,head,sizeof(iter));
    			int f;
    			while((f=dfs(s,t,inf))>0){
    				flow+=f;
    			}
    		}
    	}
    }net;
    
    int main()
    {
    	int T;cin>>T;int ca=0;
    	while(T--)
    	{
    		int tot=0;
    		scanf("%d%d",&n,&m);
    		for(int i=1;i<=n;i++){
    			scanf("%d%d%d",a+i,b+i,s+i);
    		}
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=n;j++){
    				scanf("%d",&mat[i][j]);
    			}
    		}
    		net.init();
    		int ss=0,t=2*n+1;
    		for(int i=1;i<=n;i++){
    			int num=s[i]/m;
    			if(s[i]%m!=0) num++;
    			net.insert(ss,i,num);
    			tot+=num;
    			net.insert(i+n,t,num);
    		}
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=n;j++){
    				if(i==j) continue;
    				if(b[i]+mat[i][j]<a[j]){
    					net.insert(i,n+j,inf);
    				}
    			}
    		}
    		printf("Case %d: %d
    ",++ca,tot-net.max_flow(ss,t));
    	}
    	return 0;
    }
    
  • 相关阅读:
    安装 Java 开发工具包JDK(Windows版本)
    在sublime text 3中让.vue文件的内容变成彩色
    iOS之禁止所有输入法的表情
    iOS之UIButton扩大按钮的响应区域
    iOS之利用腾讯Bugly程序调试,测试代码bug、卡顿等情况
    iOS之在本地搭建IPv6环境测试你的app
    iOS之让UISearchBar搜索图标和placeholder靠左显示
    iOS之限制TextField的输入长度
    iOS之oc与html之间的交互(oc中调用js的方法)
    iOS之面试题:腾讯三次面试以及参考思路
  • 原文地址:https://www.cnblogs.com/chanme/p/3700076.html
Copyright © 2011-2022 走看看