• HDU 3572 最大流


    【题意】有n个任务,每个任务必须开始于第Si天之后(包括Si),结束于第Ei天之前(包括Ei),每个任务持续的时间为Pi,现在有m台机器,每台每天只能专注做其中一件任务,每个任务做的时间可以不连续。问是否存在一种方案使得这n个任务顺利完成

    【类型】最大流

    【建图】设一个源点S,将每个任务分别化成一个点,S向每个任务连一条边,容量为Pi,接着每个任务向时间Si~Ei分别连一条容量为1的边,每个时间向汇点连一条容量为m的边。这样跑最大流即可。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<string>
    #include<sstream>
    #define eps 1e-9
    #define FOR(i,j,k) for(int i=j;i<=k;i++)
    #define MAXN 10005
    #define MAXM 1000005
    #define INF 0x3fffffff
    using namespace std;
    typedef long long LL;
    int i,j,k,n,m,x,y,T,ans,big,cas,num,w,t,u,v,p,s,e,S,F,sum,max_time;
    bool flag;
    
    struct Edge{
        int u,v,weight;
        int next;
    }edge[MAXM];
    int head[MAXN]; /* head[u]表示顶点u第一条邻接边的序号, 若head[u] = -1, u没有邻接边 */
    int current;    /* 当前有多少条边 */
     
    void add_edge(int u, int v, int weight)
    {
        /* 添加正向边u->v */
        edge[current].u = u;
        edge[current].v = v;
        edge[current].weight = weight;
        edge[current].next = head[u];
        head[u] = current++;
        /* 添加反向边v->u */
        edge[current].u = v;
        edge[current].v = u;
        edge[current].weight = 0;
        edge[current].next = head[v];
        head[v] = current++;
    }
     
    int isap(int s, int e , int n)
    {
        int i,u,v,max_flow,aug,min_lev;
     
        /* 寻找增广路径的过程中, curedge[u]保存的是对于顶点u当前遍历的边, 寻找顶点u的邻接边时不用每次
         * 都从head[u]开始找, 而是从curedge[u]开始找, 这样就减少了搜索次数
         * 当增广路径找到后
         * curedge保存的就是一条增广路径了, 比如
         * 0---四-->1---六-->2--七--->3---八--->4 0,1,2,3,4是顶点号, 四六七八是边的序号
         * curedge[0] = 四, curedge[1] = 六, ... curedge[3] = 8, curedge[i]即保存找过的轨迹
         */
        int curedge[MAXN],parent[MAXN],level[MAXN];
     
        /* count[l]表示对于属于层次l的顶点个数, 如果某个层次没有顶点了,
         * 就出现断层, 意味着没有增广路径了, 这就是gap优化, 可以提前结束寻找过程
         * augment[v]表示从源点到顶点v中允许的最大流量, 即这条路线的最小权重
         */
        int count[MAXN],augment[MAXN];
     
        memset(level,0,sizeof(level));
        memset(count,0,sizeof(count));
        //初始时每个顶点都从第一条边开始找
        for (i=0;i<=n;i++)
        {
            curedge[i] = head[i];
        }
        max_flow=0;
        augment[s]=INF;
        parent[s]=-1;
        u=s;
     
        while (level[s]<n)   /* 不能写成level[s] < MAX_INT */
        {
            if (u==e)       /* 找到一条增广路径 */
            {
                max_flow+=augment[e];
                aug=augment[e];
                //debug("找到一条增广路径, augment = %d
    ", aug);
                //debug("%d", e);
                for (v=parent[e];v!=-1;v=parent[v]) /* 从后往前遍历路径 */
                {
                    i=curedge[v];
                    //debug("<--%d", v);
                    edge[i].weight-=aug;
                    edge[i^1].weight+=aug;  /* 如果i是偶数, i^1 = i+1, 如果i是奇数, i^1 = i-1 */
                    augment[edge[i].v]-=aug;
                    if (edge[i].weight==0) u=v; /* u指向增广后最后可达的顶点, 下次就从它继续找 */
                }
                //debug("
    ");
            }
            /* 从顶点u往下找邻接点 */
            for (i=curedge[u];i!=-1;i=edge[i].next) /* 从curedge[u]开始找, 而不是head[u]从头开始, curedge[u]保存的是上次找过的边 */
            {
                v=edge[i].v;
                if (edge[i].weight>0 && level[u]==(level[v]+1))  /* 找到一条边就停止 */
                {
                    augment[v]=min(augment[u],edge[i].weight);
                    curedge[u]=i;
                    parent[v]=u;
                    u=v;
                    break;
                }
            }
            if (i==-1)  /* 没有邻接点, 回溯到上一个点 */
            {
                if (--count[level[u]]==0)
                {
                    //debug("顶点%d在level %d断层
    ", u, level[u]);//GAP优化
                    break;
                }
                curedge[u]=head[u]; /* 顶点u的所有边都试过了,没有出路, 更新了u的level后, 又从第一条边开始找 */
                //找出level最小的邻接点
                min_lev=n;
                for (i=head[u];i!=-1;i=edge[i].next)
                {
                    if (edge[i].weight>0)
                    {
                        min_lev=min(level[edge[i].v],min_lev);
                    }
                }
                level[u]=min_lev+1;
                count[level[u]]++;
                //debug("顶点%d的level= %d
    ", u, level[u]);
                //debug("顶点%d走不通, 回到%d
    ", u, edge[curedge[u]].u);
                if (u!=s) u=parent[u];  /* 回退到上一个顶点 */
            }
        }
        return max_flow;
    }
     
    int main()
    {
    	scanf("%d",&T);
    	for (cas=1;cas<=T;cas++)
    	{
    		memset(head,-1,sizeof(head));current=0;
    		scanf("%d%d",&n,&m);
    		S=0;sum=0;
    		max_time=0;
    		for (i=1;i<=n;i++)
    		{
    			scanf("%d%d%d",&p,&s,&e);
    			sum+=p;
    			max_time=max(max_time,e);
    			add_edge(S,i,p);
    			for (j=s;j<=e;j++)
    			{
    				add_edge(i,n+j,1);
    			}
    		}
    		F=n+max_time+1;
    		for (i=1;i<=max_time;i++)
    		{
    			add_edge(n+i,F,m);
    		}
    		if (isap(S,F,F)==sum) printf("Case %d: Yes
    
    ",cas);
    		else printf("Case %d: No
    
    ",cas);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    两个List集合过滤出不同集合
    TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body.
    sql server 查询某个表被哪些存储过程调用
    SQL server字符分割
    oracle 结果集合并
    tree与GridView交互
    oracle job相关
    ImportFileHandler 附件上传
    dt转换List CovertListHelper
    node版本管理mac版
  • 原文地址:https://www.cnblogs.com/zhyfzy/p/4147317.html
Copyright © 2020-2023  润新知