POJ 1716 Integer Intervals(差分約束模板題)
阿新 • • 發佈:2018-11-19
題意:
給出n個區間,現在要你找出一個點集,使得這n個區間都至少有2個元素在這個點集裡面,問這個點集最少有幾個點。
解析:
差分約束
用sum[i]代表[1,i]這段區間內被選中的點的數量
那麼對於[a,b]可以構造不等式
第二個式子是因為[a,b]裡面要有2個元素選中,那麼[a,b-1]至少要有1個元素被選中
然後對於所有的sum[i],體現他字首的性質
然後因為a可以到0,所以我就把所有座標向右移了1單位,那麼我們就從0出發,找一邊最長路(最小值解)就可以了。
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int MAXN = 1e4+100; #define INF 0x3f3f3f3f typedef struct node { int v; int w; }node; vector<node> edge[MAXN]; int vis[MAXN]; int d[MAXN],n; void spfa(int src) { for(int i=0;i<=n;i++) d[i]=-1,vis[i]=0; d[src]=0; queue<int> q; q.push(src); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=0;i<edge[u].size();i++) { node x=edge[u][i]; int tmp=d[u]+x.w; if(d[x.v]<tmp) { d[x.v]=tmp; if(!vis[x.v]) { vis[x.v]=1; q.push(x.v); } } } } } int main() { int m; scanf("%d",&m); for(int i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); //a++; a++; //b++; b++; edge[a-1].push_back(node{b,2}); edge[a-1].push_back(node{b-1,1}); //edge[a-1].push_back(node{b-2,0}); n=max(n,b); } for(int i=1;i<=n;i++) { edge[i-1].push_back(node{i,0}); } spfa(0); printf("%d\n",d[n]); }