zoukankan      html  css  js  c++  java
  • HDU3572构造图的模型

    第一次面对建模的图,也映照了我以前想的算法不是重点,问题的转化才是重点

    Description:

      N个任务,M台机器,对于每一个任务有p,s,e表示该任务要做p个时长,要从[s,……)开始,从(……e]结束,问你这些任务最后能完成吗Yes || No

    Solution:

      做的是最大流专辑,知道是最大流的题目,但是就是不知道怎么转化为最大流的问题。。。

      Yes or No的关键就是最大流能否等于任务总时长,面对这个题,对于每一个任务 i ,从源点到i添加一条边,边的权值(容量)是对应任务的p,如果yes是不是从s流出的量 fmax == sum(p),假设这些流量流到了任务,那么任务如何处理呢,就是看看时间段如何分配,因为可以任意时间段开始,暂停直到结束所以每个任务与它对应的每一个时间段都要添加一个1(容量),不管这个任务咋分配,只要能分配给它的p就行了,那分配好时间段了呢,是不是还有一个条件也就是机器数目,同一个时间最多m个机器工作,所以每一个时间段,都要向汇点T,传入一个m的容量,表示的意义也很明显啦,最后求出最大流就好了!真舒服,第一次懂一类题的感觉应该都是这样的吧略略略

     要注意一下,最多有多少边哈·

    #include <iostream>
    #include <cstdio>
    #include <string.h>
    #include <queue>
    #include <cmath>
    #include <algorithm>
    
    #define inf (1 << 28)
    using namespace std;
    typedef long long ll;
    const int maxn = 5000;
    const int maxm = 251000+7;
    int n,m;
    int S,T;
    struct node{
        int pre;
        int to,cost;
    }e[maxm<<1];
    int id[maxn],cnt;
    int flor[maxn];
    
    int cur[maxn];//DFS的优化遍历
    
    void add(int from,int to,int cost)
    {
        e[cnt].to = to;
        e[cnt].cost = cost;
        e[cnt].pre = id[from];
        id[from] = cnt++;
        swap(from,to);
        e[cnt].to = to;
        e[cnt].cost = 0;
        e[cnt].pre = id[from];
        id[from] = cnt++;
    }
    
    int bfs(int s,int t)
    {
        memset(flor,0,sizeof(flor));
        queue < int > q;
            while(q.size())q.pop();
        flor[s] = 1;
        q.push(s);
    
        while(q.size())
        {
            int now = q.front();
            q.pop();
            for(int i = id[now];~i;i=e[i].pre)
            {
                int to = e[i].to;
                int cost = e[i].cost;
                if(flor[to] == 0 && cost > 0)
                {
                    flor[to] = flor[now] + 1;
                    q.push(to);
                    if(to == t)return 1;
                }
            }
        }
        return 0;
    }
    int dfs(int s,int t,int value)
    {
        //ret表示目前流到s的最大流量,用来计算回溯的时候是否还有可行流
        int ret = value;
        if(s == t || value == 0)return value;
    
        int a;
    
        for(int &i = cur[s];~i;i = e[i].pre)
        {
            int to = e[i].to;
            int cost = e[i].cost;
            if(flor[to] == flor[s] + 1 && (a = dfs(to,t,min(ret,cost))))
            {
                e[i].cost -= a;
                e[i^1].cost += a;
                ret -= a;
                if(ret == 0)break;
            }
        }
        //s点后面没有可行的流了
        if(ret == value) flor[s] = 0;
        return value - ret;
    }
    int dinic(int s,int t)
    {
        ll ret = 0;
        while(bfs(s,t))
        {
            memcpy(cur,id,sizeof(id));
            ret += dfs(s,t,inf);
        }
        return ret;
    }
    void init()
    {
        memset(id,-1,sizeof(id));
        cnt = 0;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        int cas = 0;
        while(t--)
        {
            scanf("%d%d",&n,&m);
            init();
            int p,s,e;
            int tl = -1,tr = -1;
            S = 0;
            int sump = 0;
            for(int i = 1;i <= n;++i)
            {
                scanf("%d%d%d",&p,&s,&e);
                sump += p;
                add(S,i,p);
                if(tl == -1)tl = s;
                if(tr == -1)tr = e;
                tl = min(tl,s);
                tr = max(tr,e);
    
                for(int j = s;j <= e;++j)
                {
                    add(i,n+j,1);
                }
            }
            T = n + tr + 1;
            for(int i = tl;i <= tr;++i)
            {
                add(n + i,T,m);
            }
            ll ret = dinic(S,T);
            printf("Case %d: %s
    
    ",++cas,ret == sump ? "Yes" : "No");
        }
        return 0;
    }
    
  • 相关阅读:
    cb快捷键
    N的阶乘的长度 V2(斯特林近似)
    最大子序列和(Max Sum ,Super Jumping! Jumping! Jumping! )
    关于莫比乌斯和莫比乌斯反演
    最少拦截系统
    set用法详解
    几种数学公式(环排列 母函数 唯一分解定理 卡特兰数 默慈金数 贝尔数 那罗延数)
    最小堆算法
    并查集算法
    dijkstra算法演示
  • 原文地址:https://www.cnblogs.com/DF-yimeng/p/9683539.html
Copyright © 2011-2022 走看看