给出$m$个区间$[l_i,r_i]$覆盖$S=[1,n]$,试确定最大特殊点的数使得这每一个区间覆盖且仅覆盖一个特殊点。
如果无解,输出$-1$ 对于100%的数据$n\leq 2\times 10^5 , m\leq 10^5$,数据较弱。
Sol1 : 设$ w_i$ 表示$ [1,i] $特殊点数目,那么对于每个区间的约束,有且仅有$1$个就等价于$w_r-w_{l-1}=1$
我们考虑每一个点只可能是特殊点或不是特殊点,那么就是$0 \leq w_i - w_{i-1} \leq 1$
又上面的式子$w_r-w_{l-1}=1$也可以化成不等式来表示$1 \leq w_r-w_{l-1} \leq 1$
也就是$w_r - w_{l-1} \leq 1 , w_{l-1} -w_r \leq -1$ , 结合$w_{i-1} - w_i \leq 0$我们就可以跑差分约束系统了。
把$dist\{ i,i-1 \} =0 , dist\{l-1,r\}=1 ,dist\{r,l-1\}=-1$建图跑SPFA(注意判负环!!!)然后到时间输出-1弹出就可以啦。
复杂度$O($卡时间$)$
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<deque> #define Endl endl;//qwq using namespace std; const int maxn=1e6; int n,m,cnt=1; int head[maxn],vis[maxn],dis[maxn]; struct node { int nxt; int to; int w; }edge[maxn]; void add(int x,int y,int z) { edge[cnt].to=y;edge[cnt].w=z;edge[cnt].nxt=head[x];head[x]=cnt++; } //int cn[maxn]; int l,r; int tot=0; int spfa() { deque<int> q;//双端队列优化spfa memset(dis,0x3f,sizeof(dis)); dis[0]=0;//从0开始的原因见下面 vis[0]=1; q.push_back(0); while(q.size()) { int x=q.front(); q.pop_front(); vis[x]=0; for(int i=head[x];i;i=edge[i].nxt) { int y=edge[i].to,z=edge[i].w; if(dis[y]>dis[x]+z) { dis[y]=dis[x]+z; //cn[y]=cn[x]+1; if(!vis[y]) { if(++tot>1926817) return -1;//人要有点信仰,这是梦想spfa的核心部分 //if(cn[y]>n)return -1;这是正儿八经的判负环,请一定要学会 vis[y]=1; if(q.size()&&dis[y]>dis[q.front()])q.push_back(y); else q.push_front(y); } } } } return dis[n]; } int main() { cin>>n>>m; for(int i=1;i<=m;i++) { cin>>l>>r; add(l-1,r,1); add(r,l-1,-1); } for(int i=1;i<=n;i++) add(i,i-1,0),add(i-1,i,1);//i-1可能为0,所以上面最短路要从0开始跑(前后呼应~~手动滑稽) cout<<spfa()<<Endl; return 0; }