这题目是pku1201的简化版本,稍微改一下输入就AC了
题目大意:给 n 个区间,从每个区间至少取两个不同的元素。求形成的新的集合最少包含多少个元素。
* 思路:对于每个区间 [ ai , bi ]至少取两个元素 => num [ b ] - num [ a - 1 ] >= 2
* 隐含条件: 1 >= num [ i ] - num [ i - 1 ] >=0
* 求:num [ max ] - num [ min - 1 ] >= ans;
刚发现一个问题,不知道自己有没有理解错:
看下面俩段代码:
1)
// for(int i=min1;i<=max1;i++)
// dis[i]=-MAXINT;//对dis[]的初始化为负无穷小
//if(dis[tmp]<dis[t]+e[j].w)//松弛操作
// dis[tmp]=dis[t]+e[j].w;
2)
//for (i = 0; i < max1; i++)
//dis[i]=MAXINT;//
//if(dis[tmp]>dis[t]+e[j].w)//松弛操作
// dis[tmp]=dis[t]+e[j].w;
上面俩段代码是分别对应于各自的加边操作,也就是你如何构图的
num [ b+1 ] - num [ a ] >= 2对于这个约束条件,若add(a,b+1,2)则对应于第一段代码
若add(b+1,a,-2)则 对应于第二段代码,这俩段代码都是为了满足dis[b+1]>=dis[a]+2;
说来惭愧,做了好几道题目了, 才刚理解透这一点
#include<iostream> #define MAXINT 9999999 #define MAXN 10010 using namespace std; int vis[MAXN],dis[MAXN],n,num,min1,max1; int root[MAXN],stack[MAXN*5]; struct edge { int u,w,next; }e[MAXN*5]; void add(int u,int v,int len) { e[num].u=v; e[num].w=len; e[num].next=root[u]; root[u]=num++; } void spfa() { int top=0; for(int i=min1;i<=max1;i++) dis[i]=-MAXINT; dis[min1]=0; stack[++top]=min1; vis[min1]=1; while(top) { int t=stack[top--],tmp; vis[t]=0; for(int j=root[t];j!=-1;j=e[j].next) { tmp=e[j].u; if(dis[tmp]<dis[t]+e[j].w) { dis[tmp]=dis[t]+e[j].w; if(!vis[tmp]) { vis[tmp]=1; stack[++top]=tmp; } } } } } int main() { int a,b; while(cin>>n) { num=0; memset(root,-1,sizeof(root)); memset(vis,0,sizeof(vis)); min1=MAXINT;max1=-MAXINT; for(int i=0;i<n;i++) { cin>>a>>b; min1=min(a,min1); max1=max(b+1,max1); add(a,b+1,2); } for(int i=0;i<max1;i++) { add(i,i+1,0); add(i+1,i,-1); } spfa(); cout<<dis[max1]<<endl; } return 0; }