建模方法:
用数组dist[i]表示从点0到点i-1所包含的关键点的数目;
输入数据即可转化为:dist[b+1]-dist[a]>=2 => dist[a]-dist[b+1]<=-2
根据实际情况还有两个约束条件:
dist[i+1]-dist[i]<=1
dist[i+1]-dist[i]>=0 => dist[i]-dist[i]+1<=0
于是可以建图,SPFA。
最后输出dist[max]-dist[min]即可(max与min 为输入数据出现的最大点和最小点)
#include <stdio.h> #include <string.h> #define maxn 150010 #define inf 1000000000 int head[maxn], pnt[maxn], next[maxn], length[maxn]; int tot; int dist[maxn]; int queue[10000000]; int inq[maxn]; int countq[maxn]; int n; int a,b,len; int max,min; void addedge(int a,int b,int len) { pnt[tot]=b; length[tot]=len; next[tot]=head[a]; head[a]=tot++; } void spfa(int src) { int qhead=0; int qtail=1; for(int i=min; i<=max; i++) { dist[i]=inf; inq[i]=0; countq[i]=0; } dist[src]=0; inq[src]=1; countq[src]=1; queue[qhead]=src; while (qhead<qtail) { int idx=head[queue[qhead]]; while (~idx) { if (dist[pnt[idx]] > dist[queue[qhead]] + length[idx]) { dist[pnt[idx]] = dist[queue[qhead]] + length[idx]; if(!inq[pnt[idx]]) { inq[pnt[idx]]=1; countq[pnt[idx]]++; queue[qtail++]=pnt[idx]; } } idx=next[idx]; } inq[queue[qhead]]=0; qhead++; } } int main() { memset(head,-1,sizeof(head)); memset(next,-1,sizeof(next)); scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%d%d",&a,&b); addedge(b+1,a,-2); if(a>max) max=a; if(b+1>max) max=b+1; if(a<min) min=a; if(b<min) min=b+1; } for (int i=0; i<max; i++) { addedge(i,i+1,1); addedge(i+1,i,0); } spfa(max); printf("%d\n",dist[max]-dist[min]); }