题意:给你一些区间,问你确定一个集合,使得这个集合和这些区间至少有两个数字相同,求这个集合最小元素个数
思路:令d[i]为0到i区间的不同元素个数,那么有d[b]-d[a-1]>=2,d[i+1]>=d[i],d[i]>=d[i+1]-1,d[i]>=d[0],然后建边跑最长路求最小值就可以了,这里区间从0开始计数,我就都++了,如果不++的话那么要变成d[b+1]-d[a]>=2,这样跑了980MS...而我这样居然只跑了500MS..
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define inf -1e9
const int maxn = 10005;
vector<pair<int,int> >e[maxn];
int d[maxn],cnt[maxn],inq[maxn],n;
int spfa(int num)
{
memset(cnt,0,sizeof(cnt));
memset(inq,0,sizeof(inq));
for(int i = 0;i<=num;i++)
d[i]=inf;
inq[0]=1;
queue<int>q;
d[0]=0;
q.push(0);
while(!q.empty())
{
int u = q.front();
q.pop();
inq[u]=0;
for(int i =0;i<e[u].size();i++)
{
int v = e[u][i].first;
if(d[v]<d[u]+e[u][i].second)
{
d[v]=d[u]+e[u][i].second;
if(!inq[v])
{
inq[v]=1;
q.push(v);
if(++cnt[v]>n)
return false;
}
}
}
}
return 1;
}
int main()
{
int num = 0;
while(scanf("%d",&n)!=EOF)
{
for(int i = 0;i<=num;i++)
e[i].clear();
num = 0;
for(int i = 1;i<=n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
u++,v++;
num = max(num,v);
e[u-1].push_back(make_pair(v,2));
}
for(int i = 1;i<=num;i++)
{
e[0].push_back(make_pair(i,0));
e[i].push_back(make_pair(i+1,0));
e[i+1].push_back(make_pair(i,-1));
}
spfa(num);
printf("%d\n",d[num]);
}
}