差分约束整理

   


一直不知道差分约束是什么类型题目,最近在写最短路问题就顺带看了下,原来就是给出一些形如x-y<=b不等式的约束,问你是否满足有解的问题

好神奇的是这类问题竟然可以转换成图论里的最短路径问题,下面开始详细介绍下

比如给出三个不等式,b-a<=k1,c-b<=k2,c-a<=k3,求出c-a的最大值,我们可以把a,b,c转换成三个点,k1,k2,k3是边上的权,如图

由题我们可以得知,这个有向图中,由题b-a<=k1,c-b<=k2,得出c-a<=k1+k2,因此比较k1+k2和k3的大小,求出最小的就是c-a的最大值了

根据以上的解法,我们可能会猜到求解过程实际就是求从a到c的最短路径,没错的....简单的说就是从a到c沿着某条路径后把所有权值和k求出就是c -a<=k的一个

推广的不等式约束,既然这样,满足题目的肯定是最小的k,也就是从a到c最短距离...

(以上来自博客http://www.cnblogs.com/void/archive/2011/08/26/2153928.html)

去做题了 ,先占个位置  防止自己不做了=,=


POJ 3159

比较裸的一题差分约束 然而用spfa+queue 时间超限了

看了别人的代码,补上比较好的代码

 /*------------------------------------------------------------------- 
     * Purpose: 
     *         POJ 3159 candies 做了一些优化 
     * Time: 
     *         2012年3月21日 9:27:16 
     * Author: 
     *         张彦升 
     -------------------------------------------------------------------*/  
    #include <iostream>  
    #include <stdio.h>  
    #include <string.h>  
      
    using namespace std;  
      
    const int INF = 0x3f3f3f3f;  
    const int V = 30001;  
    const int E = 150001;  
      
    int pnt[E],cost[E],nxt[E];  
      
    int e,head[V];  
    int dist[V];  
    bool vis[V];  
      
    int relax(int u,int v,int c)  
    {  
        if (dist[v] > dist[u] + c)  
        {  
            dist[v] = dist[u] + c;  
            return 1;  
        }  
        return 0;  
    }  
    /** 
     * 读取一个int 
     */  
    inline int read_int()  
    {  
        int ret=0;  
        char tmp;  
        while(!isdigit(tmp=getchar()));  
        do{  
            ret=(ret<<3)+(ret<<1)+tmp-'0';  
        }while(isdigit(tmp=getchar()));  
        return ret;  
    }  
    void addedge(int u,int v,int c)  
    {  
        pnt[e] = v;  
        cost[e] = c;  
        nxt[e] = head[u];  
        head[u] = e++;  
    }  
    int SPFA(int src,int n)  
    {  
        int i;  
        for (i = 1;i <= n;i ++)  
        {  
            vis[i] = 0;  
            dist[i] = INF;  
        }  
        dist[src] = 0;  
        int Q[E],top = 1;  
        Q[0] = src;  
        vis[src] = true;  
        while (top)  
        {  
            int u,v;  
            u = Q[--top];  
            vis[u] = false;  
            for (i = head[u];i != -1;i = nxt[i])  
            {  
                v = pnt[i];  
                if (1 == relax(u,v,cost[i]) && !vis[v])  
                {  
                    Q[top++] = v;  
                    vis[v] = true;  
                }  
            }  
        }  
        return dist[n];  
    }  
      
    int main()  
    {  
        int n,m;  
        while (scanf("%d%d",&n,&m) != EOF)  
        {  
            int i,a,b,c;  
            e = 0;  
            memset(head,-1,sizeof(head));  
            for (i = 0;i < m;++i)  
            {  
                //cin >> a >> b >> c;  
                a = read_int();  
                b = read_int();  
                c = read_int();  
                addedge(a,b,c);  
            }  
            cout << SPFA(1,n) << endl;  
        }  
        return 0;  
    }  
在读入int的时候做了优化,不过个人觉得假如卡scanf读取int的时间的话真是丧尽天良= =
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值