poj 1716(最长路+差分约束系统)

来源:互联网 发布:linux 平台 编辑:程序博客网 时间:2024/06/10 01:58

题意:给出n个区间,现在要你找出一个点集,使得这n个区间都至少有2个元素在这个点集里面,问这个点集最少有几个点。

 

思路:spfa+差分约束,当然贪心也可以做,应该更快。与1201题相似,关键在于用dict[i]表示区间[0, i]上在这个点集的元素个数,具体解法详见poj 1201 :Intervals。

分析:求最小,所以差分约束的等式 在大于左边

dis[i] 保存从最小值到 i 需要的点数

有状态如下:对于一个区间a,b dis[b+1] - dis[a] >= 2; 0<=dis[i]-dis[i-1]<=1

连边 ,求最长路,即所求的最小值


#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <queue>using namespace std;#define maxn 233333int m;int mm;int mi;struct node{    int des;    int nxt;    int val;};node data[maxn] ;int head[maxn];int inq[maxn];int dis[maxn];int cnt;void addege(int u,int v,int w){    data[cnt].des = v;    data[cnt].val = w;    data[cnt].nxt = head[u];    head[u] = cnt++;}int spfa(){    for(int i = 0  ; i <= mm ; ++i)dis[i]  = -1e9;    memset(inq,0,sizeof(inq));    queue<int>Q;    Q.push( mi );    dis[mi] = 0;    inq[mi] = 1;    while(!Q.empty())    {        int u = Q.front();        Q.pop();        inq[u] = 0;        for(int i = head[u] ; ~i ; i = data[i].nxt)        {            int v = data[i].des;            int w = data[i].val;            if( dis[v] < dis[u] + w )            {                dis[v] = dis[u] + w;                if( !inq[v] )                {                     inq[v] = 1;                     Q.push(v);                }            }        }    }    return dis[mm];}int main(){    while( ~scanf("%d",&m) ){        mm = 0;mi = 1e9;cnt=0;        memset(head,-1,sizeof(head));        for(int i = 1 ; i <= m ; ++i)        {            int a,b;            scanf("%d %d",&a,&b);            addege(a,b+1,2);            mm = max(mm,b+1);            mi = min(mi,a);        }        for(int i = mi ; i <= mm ; ++i)        {            addege(i,i+1,0);            addege(i+1,i,-1);        }        printf("%d\n",spfa());    }}


0 0