zoukankan      html  css  js  c++  java
  • hdu 3572 Task Schedule

    Task Schedule

    题意:有N个任务,M台机器。每一个任务给S,P,E分别表示该任务的(最早开始)开始时间,持续时间和(最晚)结束时间;问每一个任务是否能在预定的时间区间内完成;

    注:每一个任务一个时间只能由一台机器加工,(意味着可以随意离散加工的时间点,只要所用的时间点之和为P即可;将天数变成点建图)每一台机器一个时间点也只能加工一个任务;

    重点是构图:如果将任务抽象成一个点,所需的时间P变成从该点流出的流量(从源点流入边的容量~~)那么只需按照输入顺序标记为点号与源点s连边,边的容量为P即可;但是点的流量又是怎么"流"出去的呢?流出去只是"时间"问题;即一个任务点最多消耗一个时间点,输入的是一个时间区间(区间很小),我们就可以离散化时间点,之后对区间内的时间点进行连边;边权自然是1了;全部的时间点流向汇点t;边权为机器的数量m;即指每天满载运行时,看是否"最大流"能与s(源点)那边的边权之和(一个割,Yes就表示是最小割)相等;

    ps:注意在建立时间点连边的时候,时间点不是之间的Si->Ei;而是在前面n个任务之后;所以标号+n;

    Dinic算法;296MS  12452K

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<vector>
    #include<cmath>
    #include<stdlib.h>
    #include<time.h>
    #include<stack>
    #include<set>
    using namespace std;
    #define rep0(i,l,r) for(int i = (l);i < (r);i++)
    #define rep1(i,l,r) for(int i = (l);i <= (r);i++)
    #define rep_0(i,r,l) for(int i = (r);i > (l);i--)
    #define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
    #define MS0(a) memset(a,0,sizeof(a))
    #define MS1(a) memset(a,-1,sizeof(a))
    #define inf 0x3f3f3f3f
    typedef __int64 ll;
    template<typename T>
    void read1(T &m)
    {
        T x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        m = x*f;
    }
    template<typename T>
    void read2(T &a,T &b){read1(a);read1(b);}
    template<typename T>
    void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
    template<typename T>
    void out(T a)
    {
        if(a>9) out(a/10);
        putchar(a%10+'0');
    }
    const int N = 1000;
    const int M = 101000;
    int head[N],tot;
    struct Edge{
        int from,to,cap,flow,Next;
        Edge(){}
        Edge(int from,int to,int cap,int Next):from(from),to(to),cap(cap),flow(0),Next(Next){}
    }e[M<<1];
    inline void ins(int u,int v,int w)
    {
        //cout<<" ........... "<<u<<" "<<v<<" "<<w<<endl;
        e[tot] = Edge{u,v,w,head[u]};
        head[u] = tot++;
    }
    int vis[M],s,t,cur[M],d[M];
    queue<int> Q;
    int BFS()
    {
        rep1(i,s,t) vis[i] = 0;
        vis[s] = 1;d[s] = 0;
        Q.push(s);
        while(!Q.empty()){
            int u = Q.front();Q.pop();
            for(int i = head[u];~i;i = e[i].Next){
                int v = e[i].to;
                if(!vis[v] && e[i].cap > e[i].flow){ // 只考虑残量网络的弧
                    vis[v] = 1;
                    d[v] = d[u] + 1;
                    Q.push(v);
                }
            }
        }
        return vis[t];
    }
    int DFS(int x,int a)// a表示目前为止所有弧的最小残量
    {
        if(x == t || a == 0) return a;
        int& i = cur[x];//回溯时会多次DFS到同一个点
        if(i == 0) i = head[x];
        int flow = 0, f;
        for(;~i;i = e[i].Next){// 从上次考虑的弧开始
            int v = e[i].to;
            if(d[v] == d[x]+1 && (f = DFS(v,min(a,e[i].cap - e[i].flow))) > 0){
                e[i].flow += f;
                e[i^1].flow -= f;
                flow += f;
                a -= f;// 残量-流量
                if(a == 0)   break;
            }
        }
        return flow;
    }
    int Dinic()
    {
        int flow = 0;
        while(BFS()){//在残量网络基础上不断刷新层次图;
            rep1(i,s,t) cur[i] = 0;//记录当前探索到的点的弧的编号
            flow += DFS(s,inf);
        }
        return flow;
    }
    int main()
    {
        int n,m,T,kase = 1;
        read1(T);
        while(T--){
            s = 0;
            int mn = inf,mx = 0,sum = 0;
            MS1(head);tot = 0;
            read2(n,m);
            rep1(i,1,n){
                int P,S,E;
                read3(P,S,E);
                sum += P;
                mn = min(mn,S);
                mx = max(mx,E);
                ins(i,s,P);ins(s,i,P);
                rep1(j,n+S,n+E){//与日期连边的时候要注意标号
                    ins(i,j,1);ins(j,i,1);
                }
            }
            t = n+mx+1;
            rep1(i,n+mn,n+mx){
                ins(i,t,m);ins(t,i,m);
            }
            //cout<<mn<<" "<<mx<<endl;
            printf("Case %d: %s",kase++,sum == Dinic()?"Yes":"No");
            puts("");puts("");
        }
        return 0;
    }
    View Code

    ISAP一直处于RE状态。。无语了。上面Dinic代码原本数组是开小了的,但是过了。在ISAP中改好了,却一直RE。不知道还有其他的原因会导致RE..找不出来

    先贴一发;若看出bug,直接评论即可

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<vector>
    #include<cmath>
    #include<stdlib.h>
    #include<time.h>
    #include<stack>
    #include<set>
    using namespace std;
    #define rep0(i,l,r) for(int i = (l);i < (r);i++)
    #define rep1(i,l,r) for(int i = (l);i <= (r);i++)
    #define rep_0(i,r,l) for(int i = (r);i > (l);i--)
    #define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
    #define MS0(a) memset(a,0,sizeof(a))
    #define MS1(a) memset(a,-1,sizeof(a))
    #define inf 0x3f3f3f3f
    typedef __int64 ll;
    template<typename T>
    void read1(T &m)
    {
        T x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        m = x*f;
    }
    template<typename T>
    void read2(T &a,T &b){read1(a);read1(b);}
    template<typename T>
    void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
    template<typename T>
    void out(T a)
    {
        if(a>9) out(a/10);
        putchar(a%10+'0');
    }
    const int N = 1110;
    const int M = 505000;
    int head[N],tot;
    struct Edge{
        int from,to,cap,flow,Next;
        Edge(){}
        Edge(int from,int to,int cap,int Next):from(from),to(to),cap(cap),flow(0),Next(Next){}
    }e[M];
    inline void ins(int u,int v,int cap)
    {
        //cout<<" ........... "<<u<<" "<<v<<" "<<w<<endl;
        e[tot] = Edge{u,v,cap,head[u]};
        head[u] = tot++;
    }
    int d[N],s,t;
    queue<int> Q;
    void BFS()//逆向求解到汇点的最短距离;
    {
        rep1(i,s,t) d[i] = inf;
        d[t] = 0;
        Q.push(t);
        while(!Q.empty()){
            int v = Q.front();Q.pop();
            for(int i = head[v];~i;i = e[i].Next){
                int u = e[i].to;// 还是to;无向边
                if(d[u] > d[v] + 1 && e[i].cap > e[i].flow){
                    d[u] = d[v] + 1;
                    Q.push(u);
                }
            }
        }
    }
    int cur[N],num[N],p[N];
    int Augment()
    {
        int x = t,a = inf;
        while(x != s){ //从汇点逆推得到可改进量a;
            a = min(a, e[p[x]].cap - e[p[x]].flow);
            x = e[p[x]].from;
        }
        x = t;
        while(x != s){ // 逆推,进行增广
            e[p[x]].flow += a;
            e[p[x]^1].flow -= a;
            x = e[p[x]].from;
        }
        return a;
    }
    int Maxflow()
    {
        BFS();
        MS0(num);
        rep1(i,s,t) num[d[i]]++;
        int x = s,flow = 0;
        MS0(cur);
        while(d[s] < t){
            if(x == t){
                flow += Augment();
                x = s;
            }
            int ok = 0,id = cur[x];
            if(id == 0) id = head[x];
            for(;~id;id = e[id].Next){
                int v = e[id].to;
                if(d[x] == d[v] + 1 && e[id].cap > e[id].flow){
                    ok = 1;
                    p[v] = id;//前进中记录下路径的标号;以v为索引;
                    cur[x] = id;//记录下当前u点的弧,和Dinic一样为了优化
                    x = v;
                    break;
                }
            }
            if(!ok){//点x没有找到可行的弧,认为原因出在d[]
                if(--num[d[x]] == 0) break;//gap优化 因为d[x] < dist + 1;中间断层
                int dist = t - 1;// **后面dist + 1即当该点在残余网络中没有从x出发的弧,d[x] = t;
                for(int id = head[x];~id;id = e[id].Next){
                    if(e[id].cap > e[id].flow)
                        dist = min(dist, d[e[id].to]);
                }            
                num[d[x]=dist+1]++;
                cur[x] = 0;
                if(x != s) x = e[p[x]].from;//往回走是因为可能当前的节点不存在增广路了;
            }
        }
        return flow;
    }
    int main()
    {
        int n,m,T,kase = 1;
        read1(T);
        while(T--){
            s = 0;
            int mn = inf,mx = 0,sum = 0;
            MS1(head);tot = 0;
            read2(n,m);
            rep1(i,1,n){
                int P,S,E;
                read3(P,S,E);
                sum += P;
                mn = min(mn,S);
                mx = max(mx,E);
                ins(i,s,P);ins(s,i,P);
                rep1(j,n+S,n+E){//与日期连边的时候要注意标号
                    ins(i,j,1);ins(j,i,1);
                }
            }
            t = n+mx+1;
            rep1(i,n+mn,n+mx){
                ins(i,t,m);ins(t,i,m);
            }
            printf("Case %d: %s",kase++,sum == Maxflow()?"Yes":"No");
            puts("");puts("");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    多线程循环打印ABC
    程序员如何提高影响力
    一文详解bundle adjustment
    粒子滤波到底是怎么得到的?
    多视图立体匹配论文分享CasMVSNet
    入坑slam,一位博士小姐姐的科研和成长分享(考研+读研+读博)
    【车道线检测】一种基于神经网络+结构约束的车道线检测方法
    FCGF-基于稀疏全卷积网络的点云特征描述子提取(ICCV2019)
    多视图立体匹配论文分享PVA-MVSNet
    姿态估计算法汇总|基于RGB、RGB-D以及点云数据
  • 原文地址:https://www.cnblogs.com/hxer/p/5190850.html
Copyright © 2011-2022 走看看