这题目是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;
}