Poj 1201 (差分约束系统)

 

     这是我的第五道“差分约束系统”;,值得庆祝的是,本题完全是自己做出来的,没有参考任何资料,呵呵.....兴奋......

     题意理解:(题意有点费解,看了几遍才懂)第一行输入n,下面输入n个限制条件,条件的格式为 ai bi ci,  0<=ai<=bi<=50000,1<=ci<=bi-ai+1.表示在线段[ai,bi]上至少选ci个点,使被选出的点的个数最少而且满足所有的限制条件,输出这个最小值。

题目分析:

1. 开始我用每个整数(1,2,...)当做图的结点,添加边就是 add(b, a, -c),写出来之后发现连题目的样例数据都输出错误结果8.

2. 研究了一番发现这样不行,比如有两个限制条件分别为:1 3 2, 3 6 2; 那么按照上面的思路添加这两条边<3,1>=-2, <6,3>=-2; 后又可以得到边 <6,1>=-4, 意思是在线段[1,6]上至少要选4个点,而实际上不是的,应该是至少要选3个点才对,问题出哪呢??因为线段[1,3]和[3,6]有一个公共点3. 

3. 所以要换一种方式建图,对于一个条件(ai,bi,ci)实际上表示在开区间(ai-0.5, bi+0.5)上至少选ci个整数点,但是又不能把 3.5,4.5,5.5...这样的小数当做图的结点啊!再换一种,用左闭右开区间[ai, bi+1),因为取的是整数点,所以意义和闭区间[ai,bi]一样,这样,对于每个限制条件(ai,bi,ci)就可以添加边<bi+1, ai>=-ci;即 add(b+1,a,-c).

4. 仅仅添加题目给的限制条件是不够的,题目只给了每条线段上至少选的点个数,但对于线段[a,b]还有一个隐藏的最多可选点数为b-a+1个,所以要 add(a,b+1,b-a+1).

5. 为了保证图的连通性还必须添加每相邻两个整数点i,i+1的边,区间[i,i+1)上至少有0个,至多有1个,所以add(i+1,i,0); add(i,i+1,1).

6. 大功告成,样例数据正确,提交....悲剧....TLE....

7. 难道又和poj 3159 一样,把每条有向边的顺序改变一下,即把每个add(a,b,c)改成add(b,a,c)就能节约好几倍的时间,改过之后再提交....悲剧......还是TLE

8. 终于发现有些边是多余的,第4点中的add(a,b+1,b-a+1)是多余的,因为后面有了add(i,i+1,1),去掉add(a,b+1,b-a+1),再提交.....Accept.....

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#define MAXV 50005  
#define MAXE 200100  
#define INF  100000000  
struct  
{  
    int  e, v;  
} edge[MAXE];  
int minV, maxV;  
int neg;  
int dis[MAXV];  
int node[MAXV], next[MAXE];  
int Q[MAXV], vst[MAXV];  
void add(int s, int e, int v)  
{  
    edge[neg].e = e;  
    edge[neg].v = v;  
    next[neg] = node[s];  
    node[s] = neg++;  
}  
int relax(int s, int e, int v)  
{  
    if (dis[s]+v < dis[e])  
    {  
        dis[e] = dis[s]+v;  
        return 1;  
    }  
    return 0;  
}  
int SPFA(int s0)  
{  
    int i, t, p, top;  
    for (i=minV; i<=maxV; i++)  
        dis[i] = INF;  
    dis[s0] = 0;  
    Q[0] = s0;  
    top = 1;  
    vst[s0] = 1;  
    while (top)  
    {  
        t = Q[--top];  
        vst[t] = 0;  
        p = node[t];  
        while (p != -1)  
        {  
            if (relax(t, edge[p].e, edge[p].v) && !vst[edge[p].e])  
            {  
                Q[top++] = edge[p].e;  
                vst[edge[p].e] = 1;  
            }  
            p = next[p];  
        }  
    }  
    return 1;  
}  
int main()  
{  
    int  n, a, b, c, i;  
    memset(node, -1, sizeof(node));  
    minV = 50000;  
    maxV = 0;  
    scanf("%d", &n);  
    while (n--)  
    {  
        scanf("%d %d %d", &a, &b, &c);  
        add(b+1, a, -c);  
        //add(a, b+1, b-a+1); //原来这句多余了,加上这句就TLE了  
        if (minV > a) minV = a;  
        if (maxV < b+1) maxV = b+1;  
    }  
    for (i=minV; i<maxV; i++)  
    {  
        add(i+1, i, 0);  
        add(i, i+1, 1);  
    }  
    SPFA(maxV);  
    printf("%d/n", -dis[minV]);  
}


 

你可能感兴趣的:(c,struct,BI)