poj 1021--Intervals(差分约束&Bellman_Ford)

题意:要求一最小规模整数集合与给定的一系列连续整数集合[ai,bi]交集规模大于ci。

使用差分约束系统求解,而差分约束系统又可以使用Bellman_Ford求解(其证明参考算法导论),这里只说明构图方法:

  1. 设S[i]为从0,1,2,…,i与给定的一些列集合交集的个数,所以与[ai,bi]交集的规模为S[b[i]]-S[a[i]-1] >= c[i],edge = {(b[i],a[i]-1),w = -1*c[i]}。
  2. 又因为S[i]为单调不减函数,有0 <= S[I]-S[I-1] <= 1。edge = {(i,i-1),w = 0},edge = {(i-1,i),w = 1}。

最终结果就是:S[max_b]-S[min_a-1]。 注意的是:因为a[i]可能为0,所以将ai和bi都加一,易知这样是不影响结果的。 算法导论中只是说上面求出的最短路时一个可行解,并没有证明是
最优解。在课后题中要求证明使用Bellman_Ford求出的{max_x-min_x}为最小解,也即题目要求的最优解。待证

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxN 50005
#define maxE 150005

int nodeNum,edgeNum;
int min_a,max_b;
struct edge
{
    unsigned short px,py;
    int w;
}edges[maxE];

int str2num()
{
    int num = 0;
    char c;
    while((c = getchar())&&(c != ' ')&&(c != '\n')&&(c >= 0))
    {
        num *= 10;
        num += c-'0';
    }
    return num;
}

int bellman_ford()
{
    int i,j;
    int dis[maxN];
    char IsRelax;
    memset(dis,0,sizeof(dis));
    for(i = 0;i < nodeNum;i++)
    {
        IsRelax = false;
        for(j = 0;j < edgeNum;j++)
        {
            if(dis[edges[j].py] > dis[edges[j].px]+edges[j].w)
            {
                dis[edges[j].py] = dis[edges[j].px]+edges[j].w;
                IsRelax = true;
            }
        }
        if(!IsRelax) break;<span style="white-space:pre">	</span>//已经不能松弛则不可能再松弛,所有距离已达最短
    }
    printf("%d\n",dis[max_b]-dis[min_a-1]);
    return 0;
}

int main()
{
    int i;
    int intervalNum;
    int a,b,c;
    char edgeVis[maxN];
    while(~scanf("%d",&intervalNum))
    {
        getchar();
        edgeNum = 0;
        min_a = 500000;
        max_b = 0;
        memset(edgeVis,0,sizeof(edgeVis));
        while(intervalNum--)
        {
            a = str2num()+1;
            b = str2num()+1;
            c = str2num();
            edges[edgeNum].px = b;
            edges[edgeNum].py = a-1;
            edges[edgeNum++].w = -1*c;
            if(b == a) edgeVis[b] = true;
            if(min_a > a) min_a = a;
            if(max_b < b) max_b = b;
        }
        nodeNum = max_b-min_a+1;
        for(i = min_a+1;i <= max_b;i++)
        {
            edges[edgeNum].px = i-1;
            edges[edgeNum].py = i;
            edges[edgeNum++].w = 1;
            if(!edgeVis[i])   <span style="white-space:pre">	</span>//已经有更小权重的边
            {
                edges[edgeNum].px = i;
                edges[edgeNum].py = i-1;
                edges[edgeNum++].w = 0;
            }
        }
        bellman_ford();
    }
    return 0;
}

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/dingzuoer/article/details/39494733
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞