HDU 3572 Task Schedule(ISAP)

來源:互聯網
上載者:User

標籤:style   blog   http   color   使用   os   io   strong   

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=3572


題意:m台機器,需要做n個任務。第i個任務,你需要使用機器Pi天,且這個任務要在[Si  ,  Ei]區間內完成才有效。對於一個任務,只能由一個機器來完成,一個機器同一時間只能做一個任務。當然,一個任務可以分成幾段不連續的時間來完成。問,能否做完全部任務。

題意很清晰,也就是判斷是否是滿流。

對於網路流問題,模板大家都有,關鍵在於如何建圖(詳見資料)


思路:今天問了龍哥,對建圖有了一定的瞭解,建圖分為4部分,源點->X集合->Y集合->匯點(X、Y類似於二分匹配圖),確定這個4個部分後,就是找這個4個部分的關係,也就是構建容量網路

這題的X集合可以當做任務編號,Y集合當做天數(第幾天)

某任務->某一天,若是可以在這天做任務,建一條容量為1的邊,最後,把每天到匯點再建一條邊容量M(表示每台機器最多工作M個任務)即最大容量是M。

以第二組執行個體作圖(真挫。。)


模板應用的是ISAP(可當做模板),個人很傾向ISAP

Accepted 2292 KB 62 ms C++


#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <math.h>#include <queue>#define init(a) memset(a,0,sizeof(a))#define PI acos(-1,0)using namespace std;const int maxn = 1100;const int maxm = 400000;#define lson left, m, id<<1#define rson m+1, right, id<<1|1#define min(a,b) (a>b)?b:a#define max(a,b) (a>b)?a:b#define MAX INT_MAXint head[maxn], sum, bnum;int dis[maxn]; //殘量網路中節點 i 到匯點 t 的最短距離int num[maxn]; //和 t 的最短距離等於 i 的節點數量int cur[maxn]; //當前弧下標int pre[maxn]; //可增廣路上的上一條弧的編號struct node{    int v, cap;    int next;}edge[maxm];void add(int u, int v, int cap)//加邊,儲存地圖{    edge[bnum].v=v;    edge[bnum].cap=cap;    edge[bnum].next=head[u];    head[u]=bnum++;    edge[bnum].v = u;    edge[bnum].cap=0;    edge[bnum].next=head[v];    head[v] = bnum++;}void BFS(int source,int sink)//預先處理,利用反向BFS,更新dis數組{    queue<int>q;    while(q.empty()==false) q.pop();    memset(num,0,sizeof(num));    memset(dis,-1,sizeof(dis));    q.push(sink);    dis[sink]=0;    num[0]=1;    while(!q.empty())    {        int u=q.front();        q.pop();        for(int i=head[u];i!=-1;i=edge[i].next)        {            int v=edge[i].v;            if(dis[v] == -1)            {                dis[v] = dis[u] + 1;//找允許弧                num[dis[v]]++;                q.push(v);            }        }    }}int ISAP(int source,int sink,int n)//n為殘量網路中的節點到匯點的最大距離,通常節點的個數{    memcpy(cur,head,sizeof(cur));    int flow=0, u = pre[source] = source;    BFS( source,sink);//更新dis數組    while( dis[source] < n )    {        if(u == sink)        {            int df = MAX, pos;            for(int i = source;i != sink;i = edge[cur[i]].v)//追蹤增廣路路徑,最小殘量df            {                if(df > edge[cur[i]].cap)                {                    df = edge[cur[i]].cap;                    pos = i;                }            }            for(int i = source;i != sink;i = edge[cur[i]].v) //更新流量            {                edge[cur[i]].cap -= df;                edge[cur[i]^1].cap += df;            }            flow += df;            u = pos;        }        int st;        for(st = cur[u];st != -1;st = edge[st].next)// 從當前弧開始尋找允許弧        {            if(dis[edge[st].v] + 1 == dis[u] && edge[st].cap)//找到允許弧跳出            {                break;            }        }        if(st != -1)        {            cur[u] = st;            pre[edge[st].v] = u;            u = edge[st].v;        }        else        {            if( (--num[dis[u]])==0 ) break;//GAP最佳化,出現斷層結束            int mind = n;            for(int id = head[u];id != -1;id = edge[id].next)//retreat操作:更新  dis  數組            {                if(mind > dis[edge[id].v] && edge[id].cap)                {                    cur[u] = id;//修改標號的同時修改當前弧                    mind = dis[edge[id].v];                }            }            dis[u] = mind+1;            num[dis[u]]++;            if(u!=source)            u = pre[u];// 回溯繼續尋找允許弧        }    }    return flow;}void initt(){       memset(head,-1,sizeof(head));       bnum=0;}int main(){    int T, N,M,a,b,c;    int maa, sum, source, sink, n;    scanf("%d", &T);    for (int cas = 1; cas <= T; ++cas)    {        initt();        sum = 0; source = 0; maa = 0;        scanf("%d%d", &N, &M);        for (int i = 1; i <= N; i++)        {            scanf("%d%d%d", &a, &b, &c);            sum += a;            if(c > maa) maa = c;            add(source, i, a);            for (int j = b; j <= c; ++j)            {                add(i, N + j, 1);            }        }        sink = N + maa + 1;        n = sink;        for (int i = 1; i <= maa; ++i)        {            add(N + i, sink, M);        }            printf("Case %d: ", cas);        int ans = ISAP(source, sink, n);        if(ans==sum)            puts("Yes");        else            puts("No");        cout<<endl;    }    return 0;}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.