FOJ1898:Cows Arrangement(差分约束系统)

来源:互联网 发布:java是服务器语言吗 编辑:程序博客网 时间:2024/06/06 02:41
 Problem 1898 Cows Arrangement

Accept: 41    Submit: 82
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem Description

Like everyone else, cows like to stand close to their friends. Farmer Johnson has N cows numbered from 1 to N. He wants to arrange his cows to stand along the road in a straight line. The cows are standing in the same order as they are numbered. Cow 1 is standing on position 0.The ith cow (2 <= i <= N) is standing on the right of the (i-1)th cow. No two cows stand on the same position.The length of the road is 100000000.So cow N can stand on position 100000000 at most.

Some cows like each other and want to be within a certain distance of each other in line. Some really dislike each other and want to be separated by at least a certain distance. A list of ML constraints describes which cows like each other and the maximum distance by which they may be separated; a subsequent list of MD constraints tells which cows dislike each other and the minimum distance by which they must be separated.

Your job is to compute, if possible, the minimum and maximum possible position of each cow. A possible position x of a cow means that there exists one configuration satisfying the distance constraints that the cow can stand on position x.

 Input

Input contains multiple cases.

The first line contains an integer T representing the number of cases. Then following T cases.

Each test case starts with three integers N,ML,MD (1 <= N <= 1000,0 <= ML <= 1000,0 <= MD <= 1000).

Following ML lines, each line contains three integer A,B,D(1 <= A < B <= N,1 <= D <= 10000) ,representing that Cows A and B must be at most D apart.

Following MD lines, each line contains three integer A,B,D(1 <= A < B <= N,1 <= D <= 10000) ,representing that Cows A and B must be at least D apart.

 Output

For each test case, first output one line containing "Case #x:", where x is the case number (starting from 1).If it’s impossible to arrange the cows, output “Not Exist!”,otherwise output “Exist!”,then output N line, each line contain two integers. The integers in the ith line representing the minimum and maximum possible position of cow i.

 Sample Input

4
3 0 0
3 2 1
1 2 5
1 3 10
2 3 20
4 2 1
1 3 10
2 4 10
2 4 2
4 4 1
1 2 2727
1 4 9438
3 4 9140
1 3 4791
3 4 28

 Sample Output

Case #1: Exist!
0 0
1 99999999
2 100000000
Case #2: Not Exist!
Case #3: Exist!
0 0
1 9
2 10
3 19
Case #4: Exist!
0 0
1 2727
2 4791
30 9438

 Source

FOJ有奖月赛-2010年05月

经典的差分约束系统的一道题。
题目描述:给定n个牛的位置数组,d[1]=0,d[i]<d[i+1],d[i]<=10^8
题中给出了若干约数条件,有两种A,B,C (A<B)
(1)d[B]-d[A]<=C
(2)d[B]-d[A]>=C
问题就是求d的上下界
我们可以根据是要求上界还是下界来构造一个差分约束,利用上面的不等式,构造一个求最短路(求上界)和最长路的(求下界)
最短路模型:转化成>=的形式,注意负环的出现 
对于(1)转化成d[A]+C>=d[B],addedge(A,B, C)当出现d[A]+C<d[B]时,进行松弛d[B]=d[A]+C  
对于(2)转化成d[B]-C>=d[A],addedge(B,A,-C)当出现d[B]-C<d[A]时,进行松弛d[A]=d[B]-C
对每个元素d[i+1]-1>=d[i], addedge(i+1,i,-1)
最长路模型:转化成<=的形式,注意正环的出现
对于(1)转化成d[B]-C<=d[A],addedge(B,A,-C)当出现d[B]-C>d[A]时,进行松弛d[A]=d[B]-C
对于(2)转化成d[A]+C<=d[B],addedge(A,B, C)当出现d[A]+C>d[B]时,进行松弛d[B]=d[A]+C
对每个元素d[i]+1<=d[i+1], addedge(i,i+1, 1)
极限复杂度是O(V*E) 

注意:样列很水,我一开始求最长路时候构图的时候,松弛边权没加负号也能过.....吃了一次WA.....
代码:
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 1001;const int maxm = 3001;const int INF = 1000000000;const int key = 100000000;int len;typedef struct node{    int v, d;    node *next;} node;node num[maxm], *adj[maxn];int next[maxm], q[maxn * maxm], cnt[maxn], dp[maxn], l[maxn], r[maxn];bool use[maxn];void init(int size){    for (int i = 1; i <= size; ++i) adj[i] = NULL;}inline void addedge(int u, int v, int d){    num[len].v = v;    num[len].d = d;    num[len].next = adj[u];    adj[u] = &num[len++];}inline void insert(int u, int v, int d){    addedge(u, v, d);    addedge(v, u, d);}bool SPFA(int n, int s, int t, int k){    int i, j, head = 0, tail = 0, u, v, d;    node *p;    for (i = 1; i <= n; ++i)    {        dp[i] = k * INF;        use[i] = cnt[i] = 0;    }    dp[s] = 0;    q[tail++] = s;    use[s] = 1;    cnt[s]++;    while (head < tail)    {        u = q[head++];        use[u] = 0;        for (p = adj[u]; p; p = p -> next)        {            v = p -> v;            d = p -> d;            if ((k == 1 && dp[u] + d < dp[v]) || (k == 0 && dp[u] + d > dp[v]))            {                dp[v] = dp[u] + d;                if (use[v] == 0)                {                    use[v] = 1;                    q[tail++] = v;                    cnt[v]++;                    if (cnt[v] >= n) return 1;                }            }        }    }    return 0;}int rec[maxm][3];int main(){    int i, j, k, n, m1, m2, test, count = 1;    memset(next, 0, sizeof(next));    scanf("%d", &test);    while (test--)    {        scanf("%d%d%d", &n, &m1, &m2);        for (i = 0; i < m1 + m2; ++i)            scanf("%d%d%d", &rec[i][0], &rec[i][1], &rec[i][2]);        printf("Case #%d: ", count++);        //最短路        init(n);        len = 0;        addedge(1, n, key);        for (i = 1; i < n; ++i) addedge(i + 1, i, -1);        for (i = 0; i < m1; ++i) addedge(rec[i][0], rec[i][1], rec[i][2]);        for (i = m1; i < m1 + m2; ++i) addedge(rec[i][1], rec[i][0], -rec[i][2]);        if (SPFA(n, 1, n, 1))        {            printf("Not Exist!\n");            continue;        }        for (i = 1; i <= n; ++i) r[i] = dp[i];        //最长路        init(n);        len = 0;        addedge(n, 1, -key);        for (i = 1; i < n; ++i) addedge(i, i + 1, 1);        for (i = 0; i < m1; ++i) addedge(rec[i][1], rec[i][0], -rec[i][2]);        for (i = m1; i < m1 + m2; ++i) addedge(rec[i][0], rec[i][1], rec[i][2]);        if (SPFA(n, 1, n, 0))        {            printf("Not Exist!\n");            continue;        }        for (i = 1; i <= n; ++i) l[i] = dp[i];        printf("Exist!\n");        for (i = 1; i <= n; ++i)            printf("%d %d\n", l[i], r[i]);    }}


原创粉丝点击