• hdu 1534(差分约束)


    Schedule Problem

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 1715    Accepted Submission(s): 757
    Special Judge


    Problem Description
    A project can be divided into several parts. Each part should be completed continuously. This means if a part should take 3 days, we should use a continuous 3 days do complete it. There are four types of constrains among these parts which are FAS, FAF, SAF and SAS. A constrain between parts is FAS if the first one should finish after the second one started. FAF is finish after finish. SAF is start after finish, and SAS is start after start. Assume there are enough people involved in the projects, which means we can do any number of parts concurrently. You are to write a program to give a schedule of a given project, which has the shortest time.
     
    Input
    The input file consists a sequences of projects.

    Each project consists the following lines:

    the count number of parts (one line) (0 for end of input)

    times should be taken to complete these parts, each time occupies one line

    a list of FAS, FAF, SAF or SAS and two part number indicates a constrain of the two parts

    a line only contains a '#' indicates the end of a project
     
    Output
    Output should be a list of lines, each line includes a part number and the time it should start. Time should be a non-negative integer, and the start time of first part should be 0. If there is no answer for the problem, you should give a non-line output containing "impossible".

    A blank line should appear following the output for each project.

     
    Sample Input
    3 2 3 4 SAF 2 1 FAF 3 2 # 3 1 1 1 SAF 2 1 SAF 3 2 SAF 1 3 # 0
     
    Sample Output
    Case 1: 1 0 2 2 3 1 Case 2: impossible
     
    Source
     
    题意:有n个项目,每个项目有一个周期,表示完成其的时间,然后下面有一些限制,SAF a b 表示 a 的开始时间要晚于 b的结束时间,FAF,SAS,FAS类似。问每个项目最早的开始时间,依下标输出.
    题解:我们假设 a的周期是 v[a] ,开始时间是 s[a],结束时间是 e[a], b类似.
    SAF 就可以表示为 s[a] - e[b]>=0 ---->s[a] - (s[b] +v[b] )>=0 这样的话就可以列出很多个关于起点的方程,然后就设立一个超级源点,和每个起点连条长度为 0 的边,从超级源点进行 spfa,得到 low数组后依次输出即可。有环则输出 impossible,今天听说spfa只要进入 sqrt(n) 次就可以判断有没有环了,这个题还真可以。。如果有题超时的话,不妨可以试试。。不过数据强的话另当别论。
    #include <iostream>
    #include <cstdio>
    #include <string.h>
    #include <queue>
    #include <algorithm>
    #include <math.h>
    using namespace std;
    typedef long long LL;
    const int INF = 999999999;
    const int N = 1000;
    struct Edge{
        int v,w,next;
    }edge[10005];
    int head[N];
    int n,tot;
    int val[N];
    void init(){
        memset(head,-1,sizeof(head));
        tot = 0;
    }
    void addEdge(int u,int v,int w,int &k){
        edge[k].v = v,edge[k].w = w,edge[k].next = head[u],head[u] = k++;
    }
    int low[N],time[N];
    bool vis[N];
    int spfa(int s){
        for(int i=0;i<=n;i++){
            vis[i] = false;
            low[i] = -INF;
            time[i] = 0;
        }
        low[s] = 0;
        time[s]++;
        queue<int> q;
        q.push(s);
        int num = ((int)sqrt(n)+1);  ///改成根号 n 可以AC...
        while(!q.empty()){
            int u = q.front();
            q.pop();
            vis[u] = false;
            for(int k=head[u];k!=-1;k=edge[k].next){
                int v = edge[k].v,w=edge[k].w;
                if(low[v]<low[u]+w){
                    low[v] = low[u]+w;
                    if(!vis[v]){
                        vis[v] = true;
                        q.push(v);
                        if(time[v]++>num) return 0;
                    }
                }
            }
        }
        return 1;
    }
    int main(){
        int t = 1;
        while(scanf("%d",&n)!=EOF,n){
            init();
            int MAX = -1;
            for(int i=1;i<=n;i++){
                scanf("%d",&val[i]);
            }
            char str[10];
            int super = 0;
            while(scanf("%s",str)){
                if(strcmp(str,"#")==0) break;
                int a,b;
                scanf("%d%d",&a,&b);
                if(strcmp(str,"SAF")==0){
                    addEdge(b,a,val[b],tot);
                }else if(strcmp(str,"FAF")==0){
                    addEdge(b,a,-(val[a]-val[b]),tot);
                }else if(strcmp(str,"FAS")==0){
                    addEdge(b,a,-val[a],tot);
                }else{
                    addEdge(b,a,0,tot);
                }
            }
            for(int i=1;i<=n;i++){
                addEdge(super,i,0,tot);
            }
            printf("Case %d:
    ",t++);
            if(spfa(super)){
                for(int i=1;i<=n;i++){
                    printf("%d %d
    ",i,low[i]);
                }
            }else{
                printf("impossible
    ");
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    基于asp.net(C#)MVC+前端bootstrap+ztree+lodash+jquery技术-Angel工作室通用权限管理
    java架构之-负载均衡-Ribbon 的使用
    docker采用Dockerfile安装jdk1.8案例
    Redis 模糊查询删除操作
    centos7.2安装及管理docker
    git 解决每次更新代码都要输入用户名密码的解决方案
    github上的版本和本地版本冲突的解决方法
    git命令之git mergetool vi非正常退出.swp删除不了的问题
    html-webpack-plugin详解
    Webpack友好的错误提示插件friendly-errors-webpack-plugin
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5698949.html
Copyright © 2020-2023  润新知