【最大流】HDU 3572

来源:互联网 发布:美国非农数据何时公布 编辑:程序博客网 时间:2024/04/29 14:03

http://blog.csdn.net/leolin_/article/details/7354402



http://acm.hdu.edu.cn/showproblem.php?pid=3572

题意:给出n个任务+m台机器,还有一个任务处理时限+开始时间+结束时间,一个时刻里一台机器只能处理一个任务,但是一个任务可以在不同机器处理,问能否处理完所有任务?

方法:最大流。这个题的建图算是经典,因为限定每个时刻每台机器只能处理一个任务,所以可以把时间点分配给各个合法的机器...具体是先设定一个超级源点S,连向各个任务,容量为该任务所需时间,各个任务连向在范围内的时间点,容量为1(保证每个时刻xxx这个条件),所有时间点连向超级汇点T,容量为机器台数,最后求最大流,等于所有机器所需时间和的就是yes,模板用dinic


代码:

#include<iostream>#include<string>#include<algorithm>#include<cstdlib>#include<cstdio>#include<set>#include<map>#include<vector>#include<cstring>#include<stack>#include<cmath>#include<queue>using namespace std;#define CL(x,v); memset(x,v,sizeof(x));#define INF 0x3f3f3f3f#define LL long long#define REP(i,r,n) for(int i=r;i<=n;i++)#define RREP(i,n,r) for(int i=n;i>=r;i--)#define MAXN 2505struct Edge{    int from,to,cap,flow;};bool cmp(const Edge& a,const Edge& b){    return a.from < b.from || (a.from == b.from && a.to < b.to);}struct Dinic{    int n,m,s,t;    vector<Edge> edges;    vector<int> G[MAXN];    bool vis[MAXN];    int d[MAXN];    int cur[MAXN];    void init(int n){        this->n=n;        for(int i=0;i<=n;i++)G[i].clear();        edges.clear();    }    void AddEdge(int from,int to,int cap){        edges.push_back((Edge){from,to,cap,0});        edges.push_back((Edge){to,from,0,0});//当是无向图时,反向边容量也是cap,有向边时,反向边容量是0        m=edges.size();        G[from].push_back(m-2);        G[to].push_back(m-1);    }    bool BFS(){        CL(vis,0);        queue<int> Q;        Q.push(s);        d[s]=0;        vis[s]=1;        while(!Q.empty()){            int x=Q.front();            Q.pop();            for(int i=0;i<G[x].size();i++){                Edge& e=edges[G[x][i]];                if(!vis[e.to]&&e.cap>e.flow){                    vis[e.to]=1;                    d[e.to]=d[x]+1;                    Q.push(e.to);                }            }        }        return vis[t];    }    int DFS(int x,int a){        if(x==t||a==0)return a;        int flow=0,f;        for(int& i=cur[x];i<G[x].size();i++){            Edge& e=edges[G[x][i]];            if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){                e.flow+=f;                edges[G[x][i]^1].flow-=f;                flow+=f;                a-=f;                if(a==0)break;            }        }        return flow;    }    //当所求流量大于need时就退出,降低时间    int Maxflow(int s,int t,int need){        this->s=s;this->t=t;        int flow=0;        while(BFS()){            CL(cur,0);            flow+=DFS(s,INF);            if(flow>need)return flow;        }        return flow;    }    //最小割割边    vector<int> Mincut(){        BFS();        vector<int> ans;        for(int i=0;i<edges.size();i++){            Edge& e=edges[i];            if(vis[e.from]&&!vis[e.to]&&e.cap>0)ans.push_back(i);        }        return ans;    }    void Reduce(){        for(int i = 0; i < edges.size(); i++) edges[i].cap -= edges[i].flow;    }    void ClearFlow(){        for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;    }};Dinic solver;int main(){    int n,m;    int cas=0,T;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        int s=1001,t=1002;        int p,st,en;        int N=1005;        // 1~500是“天数”的点,501~500+n 表示第i个任务,        // s为超级源点,t为超级汇点        solver.init(N);        int sum=0;        for(int i=1;i<=n;i++)        {            scanf("%d%d%d",&p,&st,&en);            sum+=p;            solver.AddEdge(s,i+500,p);            for(int j=st;j<=en;j++)                solver.AddEdge(i+500,j,1);        }        for(int i=1;i<=500;i++)            solver.AddEdge(i,t,m);        int ans=solver.Maxflow(s,t,INF);        printf("Case %d: ",++cas);       // printf("ans=%d\n",ans);        if(ans==sum) puts("Yes");        else puts("No");        puts("");    }    return 0;}



0 0
原创粉丝点击