POJ1201(查分约束)

来源:互联网 发布:祛痘图片淘宝 编辑:程序博客网 时间:2024/04/29 23:15

通过这道题又进一步理解了SPFA和差分约束

我们求最最短路径是 通过松弛(if(dis[end] > dis[start] + cost[start][end])所求出来的所有点满足 dis[end] <=  dis[start] + cost[start][end]

而差分约束条件求解满足 所有 a - b <= c i  的 c 最小值 ,转换一下  a <= ci +b 这正好是SPFA松弛之后所满足的条件;


此题有b - a + 1 >= ci   我们转换下SPFA的松弛条件, 使得(if(dis[end] < dis[start] + cost[start][end]  那么dis[end] >= dis[start] + cost[start][end]

另外题中有两个隐含条件 ai+1 - ai <= 1  ai+i - ai >= 0 (如果要用ai-1-ai<=1  ai+1 - ai >=0 的话要注意 i 的值可能会为零,这就好做一个下标平移输入时+1即可



#include <iostream>
#include <string.h>
#include <stdio.h>
#include <queue>
#define INF -10000
#define MAX  50000


using namespace std;


int maxn,minn;
int num = 0;
int head[MAX+10];
int vis[MAX+10];
int dis[MAX+10];




struct Edeg
{
    int v;
    int w;
    int next;
}edge[MAX*3];


int spfa()
{
    queue<int>Q;
    for(int i=minn; i<=maxn+1; i++)
        dis[i]=INF;
    dis[minn]=0;
    memset(vis,false,sizeof(vis));
    vis[minn]=true;
    Q.push(minn);
    while(!Q.empty())
    {
        int x=Q.front();
        Q.pop();
        vis[x]=false;


        for(int i=head[x]; i!=-1; i=edge[i].next)
        {
            if(dis[edge[i].v]<dis[x]+edge[i].w)
            {
                dis[edge[i].v]=dis[x]+edge[i].w;
                if(!vis[edge[i].v])
                {
                    vis[edge[i].v]=true;
                    Q.push(edge[i].v);
                }
            }
        }
    }
    return dis[maxn];
}


void add(int u,int v,int w)
{
    edge[num].v=v;
    edge[num].w=w;
    edge[num].next=head[u];
    head[u]=num++;
}


int main()
{
    int n;
    int a,b,c;


    while(scanf("%d",&n)!=EOF)
    {
        num = 0;
        memset(head,-1,sizeof(head));
        minn = -INF;
        maxn = 0;


        while(n--)
        {
          scanf("%d%d%d",&a, &b, &c);

      //下标平移

     //a++ ; b++; 
           add(a,b+1,c);
           if(minn > a)
            minn = a;
           if(maxn < b+1)
            maxn = b+1;
        }


         for(int i=minn;i<maxn;i++)
        {
            add(i,i+1,0);
            add(i+1,i,-1);
        }


        printf("%d\n",spfa());
    }
    return 0;
}

0 0
原创粉丝点击