pku 1716 Integer Intervals

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

 

原文地址:https://www.cnblogs.com/nanke/p/2137961.html