【poj1716】 Integer Intervals
http://poj.org/problem?id=1716 (题目链接)
题意
给出n个区间,要求取出最少数量的不同的自然数,使每个区间中至少包含2个取出的数。
Solution
差分约束。
运用前缀和,将问题转化为了一些不等式,然后建图连边跑SPFA最长路(因为是>=)即可,因为有负权所以用不了dijistra。就是poj1201的简化版。
代码
// poj1716 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define LL long long #define inf 2147483640 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; inline LL getint() { int f,x=0;char ch=getchar(); while (ch<='0' || ch>'9') {if (ch=='-') f=-1;else f=1;ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();} return x*f; } const int maxn=10010; struct edge {int next,to,w;}e[maxn<<2]; int head[maxn],vis[maxn],dis[maxn],cnt,s,t,n; void link(int u,int v,int w) { e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].w=w; } void SPFA() { queue<int> q; while (q.size()) q.pop(); for (int i=s;i<=t;i++) { vis[i]=1; dis[i]=0; q.push(i); } while (q.size()) { int x=q.front(); q.pop(); vis[x]=0; for (int i=head[x];i;i=e[i].next) if (dis[e[i].to]<dis[x]+e[i].w) { dis[e[i].to]=dis[x]+e[i].w; if (!vis[e[i].to]) { q.push(e[i].to); vis[e[i].to]=1; } } } } int main() { scanf("%d",&n); s=inf,t=0; for (int x,y,i=1;i<=n;i++) { scanf("%d%d",&x,&y); link(x,y+1,2); s=min(s,x); t=max(t,y+1); } for (int i=s;i<=t;i++) link(i-1,i,0),link(i,i-1,-1); SPFA(); printf("%d",dis[t]); return 0; }
This passage is made by MashiroSky.