poj 1201

来源:互联网 发布:影子去除算法 编辑:程序博客网 时间:2024/05/19 02:24

查分约束


**要注意查分约束的隐含条件然后加一个源点,终点,用bellman_ford 或者 sfpa 

 

 Poj 1201

  大致题意:给出n个闭区间[ai,bi],每个区间对应一个ci,表示集合Z在区间[ai,bi]ci     个相同元素,问集合Z至少有几个元素。

分约束的思想:可以肯定的是s[bi]-s[ai-1]>=ci; 为什么要ai-1,是因为ai也要选进来
在一个是s[i]-s[i-1]<=1;
s[i]-s[i-1]>=0
所以整理上面三个式子可以得到约束条件:
①s[bi]-s[ai-1]>=ci;

这两个隐含条件要注意否则点根本就连不上
②s[i-1]-s[i] >=- 1
③s[i]-s[i-1>= 0 

因为这道题ai可以去零,我们就把所有结点都加上一s[bi]-s[ai-1]>=ci; --->s[ai]-s[bi+1] >=ci

 

求最长路

#include <iostream>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <queue>

 

using namespace std;

 

const int MAXN=50100;

const int INF=-0x3f3f;

struct Edge

{

    int u, v, cost, next;

};

Edge E[MAXN << 2];

int head[MAXN << 2], ecnt;

 

void AddEdge(int u,int v,int w)

{

    E[ecnt].u = u;

    E[ecnt].v = v;

    E[ecnt].cost = w;

    E[ecnt].next = head[u];

    head[u]= ecnt++;

}

 

bool vis[MAXN];//在队列标志

int cnt[MAXN];//每个点的入队列次数

int dist[MAXN];

 

bool SPFA(int start,int n, int e_cnt)

{

    memset(vis,false,sizeof(vis));

    for(int i=1; i<=n; i++)  dist[i]=INF;

    queue<int>que;

    while(!que.empty())que.pop();

    vis[start]=true;

    dist[start]=0;

    que.push(start);

    memset(cnt,0,sizeof(cnt));

    cnt[start]=1;

 

    while(!que.empty())

    {

        int u=que.front();

        que.pop();

        vis[u]=false;

        for(int i=head[u]; i != -1; i = E[i].next)

        {

            int v= E[i].v;

            int cost = E[i].cost;

            if(dist[v]<dist[u] +  cost)

            {

                dist[v]=dist[u] + cost;

                if(!vis[v])

                {

                    vis[v]=true;

                    que.push(v);

                    if(++cnt[v]>n)return false;

//cnt[i]为入队列次数,用来判定是否存在负环回路

                }

            }

        }

    }

    return true;

}

 

int main()

{

    int n;

    int a, b, c;

    while(scanf("%d",&n) != EOF)

    {

        memset(head, -1, sizeof(head));

        ecnt = 0;

        int end = 0, sta = MAXN;

        for( int i = 0; i < n; i++)

        {

            scanf("%d %d %d",&a, &b, &c);

            AddEdge(a, b+1, c);

            end = max(end, max(a, b+1));

            sta = min(sta, min(a, b+1));

        }

 

        for( int i = sta; i < end ; i++)

          {

 

              AddEdge(i, i+1, 0);

              AddEdge(i+1, i, -1);

          }

 

        SPFA(sta,end - sta + 1, ecnt);

        printf("%d\n",dist[end]);

    }

    return 0;

 

}

 

 


0 0
原创粉丝点击