zoukankan      html  css  js  c++  java
  • hdoj 3572 Task Schedule【建立超级源点超级汇点】

    Task Schedule

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 6000    Accepted Submission(s): 1922


    Problem Description
    Our geometry princess XMM has stoped her study in computational geometry to concentrate on her newly opened factory. Her factory has introduced M new machines in order to process the coming N tasks. For the i-th task, the factory has to start processing it at or after day Si, process it for Pi days, and finish the task before or at day Ei. A machine can only work on one task at a time, and each task can be processed by at most one machine at a time. However, a task can be interrupted and processed on different machines on different days.
    Now she wonders whether he has a feasible schedule to finish all the tasks in time. She turns to you for help.
     
    Input
    On the first line comes an integer T(T<=20), indicating the number of test cases.

    You are given two integer N(N<=500) and M(M<=200) on the first line of each test case. Then on each of next N lines are three integers Pi, Si and Ei (1<=Pi, Si, Ei<=500), which have the meaning described in the description. It is guaranteed that in a feasible schedule every task that can be finished will be done before or at its end day.
     
    Output
    For each test case, print “Case x: ” first, where x is the case number. If there exists a feasible schedule to finish all the tasks, print “Yes”, otherwise print “No”.

    Print a blank line after each test case.
     
    Sample Input
    2
    4 3
    1 3 5
    1 1 4
    2 3 7
    3 5 9
    2 2
    2 1 3
    1 2 2
     
    Sample Output
    Case 1: Yes
    Case 2: Yes
     
    题意:有n个任务,m个机器,给你完成第i件任务的时间以及必须完成这件任务的时间区间(si,ei),一台机器一次只能执行一个任务,让你判断是否完成所有的任务;
     
    题解:难在建图   注意: 我们是将天数看做流量
    1、将每个任务i看做一个节点连接超级源点 s,容量为每个人物所需要的时间
    2、将每个任务i看做节点, 连接完成这个任务所要进行的时间阶段内的所有点,容量为1  (表示这件任务的流量只能为1(即天数为1))
    3、将所有时间段内的点连接到超级汇点t容量为m   (表示一天内共有m台机器可以同时工作)
     
     
    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #include<stack>
    #include<algorithm>
    #define INF 0x7fffff
    #define MAX 11000
    #define MAXM 1001000
    using namespace std;
    struct node
    {
    	int from,to,cap,flow,next;
    }edge[MAXM];
    int ans,head[MAX];
    int cur[MAX];
    int vis[MAX];
    int dis[MAX];
    int sum,n,m;
    int sec;//超级汇点 
    void init()
    {
    	ans=0;
    	memset(head,-1,sizeof(head));
    }
    void add(int u,int v,int w)
    {
    	node E1={u,v,w,0,head[u]};
    	edge[ans]=E1;
    	head[u]=ans++;
    	node E2={v,u,0,0,head[v]};
    	edge[ans]=E2;
    	head[v]=ans++;
    }
    void getmap()
    {
    	int i,j,last=-1;
    	sum=sec=0;
    	int bt,et,time;
    	for(i=1;i<=n;i++)
    	{
    		scanf("%d%d%d",&time,&bt,&et);
    		sum+=time;
    		add(0,i,time);//超级源点连接第i件任务 
    		for(j=bt;j<=et;j++)
    			add(i,n+j,1);//将每件任务与完成这件任务所需要的时间段内的每一天连接 
    		last=max(last,et); 
    	}
    	sec=n+last+1;
    	for(i=1;i<=sec;i++)
    	    add(n+i,sec,m);//将所有的时间段内的点指向超级汇点 
    }
    int bfs(int beg,int end)
    {
        int i;
        memset(vis,0,sizeof(vis));
        memset(dis,-1,sizeof(dis));
        queue<int>q;
        while(!q.empty())
            q.pop();
        vis[beg]=1;
        dis[beg]=0;
        q.push(beg);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(i=head[u];i!=-1;i=edge[i].next)//遍历所有的与u相连的边
            {
                node E=edge[i];
                if(!vis[E.to]&&E.cap>E.flow)//如果边未被访问且流量未满继续操作
                {
                    dis[E.to]=dis[u]+1;//建立层次图
                    vis[E.to]=1;//将当前点标记                                                                                                            
                    if(E.to==end)//如果当前点搜索到终点则停止搜索  返回1表示有从原点到达汇点的路径
                        return 1;
                    q.push(E.to);//将当前点入队
                }
            }
        }
        return 0;//返回0表示未找到从源点到汇点的路径
    }
    int dfs(int x,int a,int end)//把找到的这条边上的所有当前流量加上a(a是这条路径中的最小残余流量)
    {
        //int i;
        if(x==end||a==0)//如果搜索到终点或者最小的残余流量为0
            return a;
        int flow=0,f;
        for(int& i=cur[x];i!=-1;i=edge[i].next)//i从上次结束时的弧开始
        {
            node& E=edge[i];
            if(dis[E.to]==dis[x]+1&&(f=dfs(E.to,min(a,E.cap-E.flow),end))>0)//如果
            {//bfs中我们已经建立过层次图,现在如果 dis[E.to]==dis[x]+1表示是我们找到的路径
            //如果dfs>0表明最小的残余流量还有,我们要一直找到最小残余流量为0
                E.flow+=f;//正向边当前流量加上最小的残余流量
                edge[i^1].flow-=f;//反向边
                flow+=f;//总流量加上f
                a-=f;//最小可增流量减去f
                if(a==0)
                    break;
            }
        }
        return flow;//所有边加上最小残余流量后的值
    }
    int Maxflow(int beg,int end)
    {
        int flow=0;
        while(bfs(beg,end))//存在最短路径
        {
            memcpy(cur,head,sizeof(head));//复制数组
            flow+=dfs(beg,INF,end);
        }
        return flow;//最大流量
    }
    int main()
    {
    	int t;
    	scanf("%d",&t);
    	int k=1;
    	while(t--)
    	{
    		scanf("%d%d",&n,&m);
    		init();
    		getmap();
    		printf("Case %d: ",k++);
    		if(sum==Maxflow(0,sec))
    		    printf("Yes
    
    ");
    		else
    		    printf("No
    
    ");
    	}
    	return 0;
    } 
    

      

     
  • 相关阅读:
    JS的编码、解码及C#中对应的解码、编码 itprobie
    word、excel、ppt转换成html itprobie
    js 导出到word,excel itprobie
    word、excel、ppt转换成pdf itprobie
    SELECT INTO 和 INSERT INTO SELECT 两种表复制语句
    Copy Table From Another Table
    系统表相关SQL语句
    sp_executesql Demo
    SQLServer2000删除重复数据
    SQL Tran Save Point
  • 原文地址:https://www.cnblogs.com/tonghao/p/4921630.html
Copyright © 2011-2022 走看看