题目含义
给出一堆区间,要求一个集合V与这些区间都共同含有两个以上不同的整数
题目分析
用sum[x]来表示[0,x]内包含V集合整数的个数
那么区间[a,b]则说明sum[b]-sum[a-1]>=2
在求最长路 if (dis[v]<dis[u]+w) dis[v]=dis[u]+w;的这个式子,可以保证dis[v]>=dis[u]+w
也就是说这道题可以变成求最长路dis[mx]的距离
但有几点需要注意
(1)a-1是作为u来加边的,而head[u]明显不能让u小于0,而a又可以为0,所以最好把sum[b+1]-sum[a]作为
sum[b]-sum[a-1]
(2)本来想用Dijkstra写的,但发现用优先队列输出的是当前dis最小的,这样求最短路当然可以,但最长度就不知道行不行,干脆还是用SPFA吧
题目代码
#include<iostream> #include<stdio.h> #include<string.h> #include<queue> using namespace std; const int maxn=1e4+7; const int INF=0x3f3f3f3f; typedef long long LL; int head[maxn],dis[maxn]; bool vis[maxn]; int tot,n,a,b; struct edge{ int to,w,next; }e[maxn*3]; //struct node{ // int pos,dis; // bool operator<(const node &x)const{ // return dis>x.dis; // } //}; void add(int u,int v,int w){ e[tot].to=v; e[tot].w=w; e[tot].next=head[u]; head[u]=tot++; } int max3(int a,int b,int c){ return max(a,max(b,c)); } void SPFA(){ queue<int>q; dis[0]=0; vis[0]=true; q.push(0); while(!q.empty()){ int u=q.front();q.pop(); vis[u]=false; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].to; if(dis[v]<dis[u]+e[i].w){ dis[v]=dis[u]+e[i].w; if(!vis[v]){ vis[v]=true; q.push(v); } } } } } int main(){ scanf("%d",&n); tot=0; int mx=0; memset(head,-1,sizeof(head)); memset(dis,-INF,sizeof(dis)); memset(vis,false,sizeof(vis)); for(int i=1;i<=n;i++){ scanf("%d%d",&a,&b); add(a,b+1,2); mx=max(mx,b+1); } for(int i=0;i<=mx;i++){ add(i,i+1,0); add(i+1,i,-1); } SPFA(); printf("%d ",dis[mx]); return 0; }