标签:差分 spfa can class 不等式 多少 next stream logs
题意:给出n个区间[a,b] n,a,b<=1e4,要求找到一个最小集合 使得每个区间至少有两个数在集合中.
设d[i]为0~i中有多少个元素在集合中,mn,mx分别为左右端点
则对每个i=1..n都要满足 d[b[i]]-d[a[i]-1]>=2
保证等式有意义,d[i+1]<=d[i]+1 , d[i]<=d[i+1]
全部化为小于号 d[a[i]-1]-d[b[i]]<=-2
若答案为ans 则d[mx]-d[mn-1]>=ans
把mx当作源点,求出到mn-1的最短路即为ans
由最短路的三角形不等式 d[v]<=d[u]+w 即 d[v]-d[u]<=w
则按照上面方式建图,求出最短路的同时,也满足了所有的约束条件
#include <iostream> #include <queue> #include <cstring> #include <cmath> #include <cstdio> #include <vector> using namespace std; typedef pair<int,int> ii; const int N=5e5+20; const int inf=1e9; struct node{ int to,next,w; }e[N]; int head[N],cnt; void insert(int u,int v,int w) { e[cnt].to=v,e[cnt].w=w,e[cnt].next=head[u]; head[u]=cnt++; } int n,inq[N],d[N]; queue<int> q; void SPFA(int s,int t) { while(!q.empty()) q.pop(); for(int i=0;i<=s;i++) inq[i]=0,d[i]=inf; q.push(s); inq[s]=1,d[s]=0; while(!q.empty()) { int u=q.front(); q.pop(),inq[u]=0; for(int i=head[u];i!=-1;i=e[i].next) { int v=e[i].to,w=e[i].w; if(d[v]>d[u]+w) { d[v]=d[u]+w; if(!inq[v]) inq[v]=1,q.push(v); // cout<<v<<‘ ‘<<d[v]<<endl; } } } cout<<d[s]-d[t]<<endl; } int main() { int w=2,a,b; while(cin>>n) { //d[b]-d[a-1]>=2 //d[a-1]<=d[b]+(-2) cnt=0; memset(head,-1,sizeof(head)); int mx=-inf,mn=inf; for(int i=1;i<=n;i++) { scanf("%d%d",&a,&b); insert(b+1,a,-2); mx=max(mx,b+1),mn=min(mn,a); } //d[i+1]<=d[i]+1 //d[i]<=d[i+1] for(int i=0;i<mx;i++) insert(i,i+1,1),insert(i+1,i,0); // cout<<mx<<‘ ‘<<mn-1<<endl; SPFA(mx,mn); } return 0; }
POJ 1716 Interger Intervals 差分约束(入门题)
标签:差分 spfa can class 不等式 多少 next stream logs
原文地址:http://www.cnblogs.com/HIKARI1149/p/7056314.html