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

Asia 1996, Shanghai (Mainland China)

题意:有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:\n",t++);
        if(spfa(super)){
            for(int i=1;i<=n;i++){
                printf("%d %d\n",i,low[i]);
            }
        }else{
            printf("impossible\n");
        }
        printf("\n");
    }
    return 0;
}
时间: 2024-11-09 18:44:34

hdu 1534(差分约束)的相关文章

hdu 1364(差分约束)

King Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 12056   Accepted: 4397 Description Once, in one kingdom, there was a queen and that queen was expecting a baby. The queen prayed: ``If my child was a son and if only he was a sound kin

hdu 3666(差分约束,手动栈解决超时问题)

THE MATRIX PROBLEM Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8016    Accepted Submission(s): 2092 Problem Description You have been given a matrix CN*M, each element E of CN*M is positive

Instrction Arrangement (hdu 4109 差分约束)

Instrction Arrangement Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1395    Accepted Submission(s): 584 Problem Description Ali has taken the Computer Organization and Architecture course th

hdu 差分约束题集

[HDU]1384 Intervals 基础差分约束★1529 Cashier Employment 神级差分约束★★★★ 1531 King 差分约束★1534 Schedule Problem 差分约束输出一组解★3440 House Man 比较好的差分约束★★3592 World Exhibition 简单★3666 THE MATRIX PROBLEM 中等★★4274 Spy's Work [先处理出欧拉序列,然后就是差分约束了...] [POJ]1201 Intervals1275

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 4594 Difference(奇圈判断+差分约束)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4598 思路:由题意可知两相连点ai符号一定相反,所以若存在奇圈则一定无解.染色,colour[i]==1表示为正,colour[i]==2表示为负.由于(b)条件为充要条件,所以对于图中的点| a[i]-a[j] | >= T,对于非图中点| a[i]-a[j] | < T,即| a[i]-a[j] | <= T-1 .所以图中点,若colour[i]==1,a[i]-a[j] >=

HDU 3666 THE MATRIX PROBLEM (差分约束)

题意:给定一个最大400*400的矩阵,每次操作可以将某一行或某一列乘上一个数,问能否通过这样的操作使得矩阵内的每个数都在[L,R]的区间内. 析:再把题意说明白一点就是是否存在ai,bj,使得l<=cij*(ai/bj)<=u (1<=i<=n,1<=j<=m)成立. 首先把cij先除到两边去,就变成了l'<=ai/bj<=u',由于差分约束要是的减,怎么变成减法呢?取对数呗,两边取对数得到log(l')<=log(ai)-log(bj)<=l

HDU 1384 Intervals【差分约束-SPFA】

类型:给出一些形如a−b<=k的不等式(或a−b>=k或a−b<k或a−b>k等),问是否有解[是否有负环]或求差的极值[最短/长路径].例子:b−a<=k1,c−b<=k2,c−a<=k3.将a,b,c转换为节点:k1,k2,k3转换为边权:减数指向被减数,形成一个有向图: 由题可得(b−a) + (c−b) <= k1+k2,c−a<=k1+k2.比较k1+k2与k3,其中较小者就是c−a的最大值.由此我们可以得知求差的最大值,即上限被约束,此时我

【转载】夜深人静写算法(四)——差分约束

[转载]夜深人静写算法(四) - 差分约束  目录     一.引例       1.一类不等式组的解   二.最短路       1.Dijkstra       2.图的存储       3.链式前向星       4.Dijkstra + 优先队列       5.Bellman-Ford       6.SPFA       7.Floyd-Warshall   三.差分约束        1.数形结合        2.三角不等式        3.解的存在性        4.最大值