HDU1534 Schedule Problem【SPFA】【差分约束】

Schedule Problem

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 1404    Accepted Submission(s): 599

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

Asia 1996, Shanghai (Mainland China)

题目大意:安排N个工作 ,给你N个工作的开始时间,共有4种安排方式(约束条件)。

条件1:FAF a b,a要在b完成后完成。

条件2:FAS a b,a在在b开始前完成。

条件3:SAS a b,a要在b开始前开始。

条件4:SAF a b,a要在b结束前开始。

给你一系列的约束条件。问:使其工作时间最小且满足所有约束条件的各个工作最早

时间各是什么。如果不满足条件则输出"impossible"。

思路:差分约束系统。设第i件工作的开始时间为t[i]。4个约束条件变成:

条件1:FAF Sa + t[a] - (Sb + t[b]) >= 0

条件2:FAS Sa + t[a] - Sb >= 0

条件3:SAS Sa - Sb >= 0

条件4:SAF Sa - (Sb + t[b]) >= 0

转换为差分约束系统:

条件1:FAF Sb - Sa <= t[a]-t[b]

条件2:FAS Sb - Sa <= t[a]

条件3:SAS Sb - Sa <= 0

条件4:SAF Sb - Sa <= -t[b]

最后求出的Dist[]数组即为各项工作开始的最早时间。不过题目要求最早开始时间为0。

所以计算出Dist[]数组中最小的项,每项工作开始的最早时间减去最小的项即为答案。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN = 1010;
const int MAXM = MAXN*MAXN;
const int INF = 0xffffff0;

struct EdgeNode
{
    int to;
    int w;
    int next;
}Edges[MAXM];
int id,Head[MAXN],Dist[MAXN],vis[MAXN],outque[MAXN],num[MAXN];

void AddEdges(int u,int v,int w)
{
    Edges[id].to = v;
    Edges[id].w = w;
    Edges[id].next = Head[u];
    Head[u] = id++;
}

bool SPFA(int s,int N)
{
    memset(vis,0,sizeof(vis));
    memset(outque,0,sizeof(outque));
    for(int i = 0; i <= N; ++i)
        Dist[i] = INF;
    queue<int> Q;
    Dist[s] = 0;
    vis[s] = 1;
    Q.push(s);
    while( !Q.empty() )
    {
        int u = Q.front();
        Q.pop();
        vis[u] = 0;
        outque[u]++;
        if(outque[u] > N)
            return false;
        for(int i = Head[u]; i != -1; i = Edges[i].next)
        {
            int temp = Dist[u] + Edges[i].w;
            if(temp < Dist[Edges[i].to])
            {
                Dist[Edges[i].to] = temp;
                if( !vis[Edges[i].to])
                {
                    vis[Edges[i].to] = 1;
                    Q.push(Edges[i].to);
                }
            }
        }
    }
    return true;
}

int main()
{
    int N,kase = 0,u,v;
    char ch[4];
    while(~scanf("%d",&N) && N)
    {
        int Min = INF;
        for(int i = 1; i <= N; ++i)
            scanf("%d", &num[i]);

        memset(Head,-1,sizeof(Head));
        id = 0;
        while(scanf("%s",ch) && ch[0] != '#')
        {
            scanf("%d%d", &u, &v);
            if(strcmp(ch,"SAS") == 0)
                AddEdges(u,v,0);
            else if(strcmp(ch,"SAF") == 0)
                AddEdges(u,v,-num[v]);
            else if(strcmp(ch,"FAS") == 0)
                AddEdges(u,v,num[u]);
            else
                AddEdges(u,v,num[u]-num[v]);
        }
        for(int i = 1; i <= N; ++i)
            AddEdges(0,i,0);
        printf("Case %d:\n",++kase);
        if(SPFA(0,N) == 0)
        {
            printf("impossible\n\n");
            continue;
        }
        for(int i = 1; i <= N; ++i)
            if(Dist[i] < Min)
                Min = Dist[i];
        for(int i = 1; i <= N; ++i)
            printf("%d %d\n", i, Dist[i]-Min);
        printf("\n");
    }
    return 0;
}
时间: 2024-11-10 10:54:42

HDU1534 Schedule Problem【SPFA】【差分约束】的相关文章

HDU1534 Schedule Problem 【差分约束系统】

Schedule Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1283    Accepted Submission(s): 534 Special Judge Problem Description A project can be divided into several parts. Each part sho

HDU1534 Schedule Problem 差分约束

囧,还是暴露出了对差分约束理解的不透彻... 一开始根据开始和结束的关系建边,然后建立一个超级源点,连接每一个其他节点,先把这个点入队.本质上相当于把一开始所有的节点都入队了,然后做一遍最长路(最短路,怎么建边的怎么来),相当于把每一个点都作为起点做了一遍最短路,每个点的d取最大的那个. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include &l

Candies---hdu3159(spfa+差分约束)

题目链接:http://poj.org/problem?id=3159 题意:有n个小孩,m个关系格式是A B C 表示小孩 B 的糖果数最多比小孩A多C个,相当于B-A<=C; 有m个这样的关系最后求小孩n比小孩1最多多几个糖果: 差分约束: 比如给出三个不等式,b-a<=k1,c-b<=k2,c-a<=k3,求出c-a的最大值, 我们可以把a,b,c转换成三个点,k1,k2,k3是边上的权,如图   由题我们可以得知,这个有向图中,由题b-a<=k1,c-b<=k2

codevs 1183 泥泞的道路 (二分+SPFA+差分约束)

/* 二分答案(注意精度) 对于每一个答案 有(s1+s2+s3...)/(t1+t2+t3...)>=ans 时符合条件 这时ans有变大的空间 对于上述不等式如果枚举每一条路显得太暴力 化简一下变成 :s1-t1*ans+s2-t2*ans+s3-t3*ans...>=0 差分约束跑最长路 如果dis[n]>0 或者有正环 (开始这个忘掉了)ans就合法 */ #include<iostream> #include<cstdio> #include<cs

Hdu 3666 THE MATRIX PROBLEM(差分约束)

题目地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=3666 思路:差分约束. 取对数将乘除转化为加减. L<=m[i][j]*a[i]/b[j]<=U log(L/m[i][j])<=log(a[i])-log(b[j])<=log(U/m[i][j]) 则 : log(a[i])<=log(b[j])+log(U/m[i][j]) log(b[j])<=log(a[i])+log(m[i][j]/L) SPFA判

HDU 3666 THE MATRIX PROBLEM (差分约束,最短路)

题意:给一个n*m矩阵,每个格子上有一个数字a[i][j],给定L和U,问:是否有这样两个序列{a1...an}和{b1...bn},满足 L<=a[i][j]*ai/bj<=U .若存在输出yes,否则no. 思路:能够得到的是一对不等式,那么可以用最短路来解决差分约束系统.但是a[i][j]*ai/bj<=U是除的,得提前变成减的才行.可以用log来解决,先不管a[i][j],logai-logbj<=U不就行了?可以得到: (1)logai - logbj<=U/a[i

HDU-1534 Schedule Problem

四种约束条件..照做就行了.. 最长路建图. #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <fstream> #include <iostream> #include <deque> #define rep(i, l, r) for(int i=l;

HDOJ 1534 Schedule Problem 差分约束

差分约数: 求满足不等式条件的尽量小的值---->求最长路---->a-b>=c----> b->a (c) Schedule Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1503    Accepted Submission(s): 647 Special Judge Problem Descr

POJ 3159 Candies(SPFA+栈)差分约束

题目链接:http://poj.org/problem?id=3159 题意:给出m给 x 与y的关系.当中y的糖数不能比x的多c个.即y-x <= c  最后求fly[n]最多能比so[1] 多多少糖? 差分约束问题, 就是求1-n的最短路,  队列实现spfa 会超时了,改为栈实现,就可以 有负环时,用栈比队列快 数组开小了,不报RE,报超时 ,我晕 #include <iostream> #include <cstdlib> #include <cstdio>