F. Radio Stations
题意:
输入n,p,M,m(都是2-4e5),
n表示由n个条件,每个条件输入x,y(1<=x<y<=p)表示x,y中至少选择一个;
p表示有p个,p行,输入li,ri表示第i个发射塔的功率在li到ri.M表示(1<=li<=ri<=M)
m表示有m个条件,每个条件输入u,v(1<=u<v<=p)表示u,v不能同时选择。
问选择哪几个发射塔和什么功率可以满足以上条件。
题解:
很明显如果没有限制l[i],r[i],就是一道2-SAT板题了,但是加了限制条件,那就稍稍修改一下2-SAT模板就好。
- 2-SAT套路:i表是选择i,i+p表示不选i(1<=i<=p)。
- 增加条件:2*p+i表示(>=i),2*p+M+i表示(<=i)(1<=i<=M)于是便可加2*p+i+1->2*p+i和2*p+M+i->2*p+M+i+1(1<=i<M)(这算是初始化加边吧),接下来才是重点,对于li,ri(1<=i<=p) 对于i加边 i->2*p+li,i->2*p+M+ri,对于i+p加边,(ri<M)2*p+ri+1->i+p,(li>1)2*p+M+li-1->i+p;于是边就建好了。
再写一下2-SAT套路吧,按套路建边,然后跑tarjan,选择tarjan跑出反拓扑序小的就好。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+9;
int n,p,M,m,l[N],r[N];
struct Edge{int v,nxt;}e[N<<2];
int head[N],cnt;
inline void add(int u,int v){e[cnt]=(Edge){v,head[u]},head[u]=cnt++;}
int dfn[N],low[N],num,co[N],col;
stack<int>S;bool vis[N];
void tarjan(int u){
dfn[u]=low[u]=++num;
S.push(u),vis[u]=1;
for(int i=head[u],v;~i;i=e[i].nxt){
v=e[i].v;
if(!dfn[v])tarjan(v),low[u]=min(low[u],low[v]);
else if(vis[v])low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
co[u]=++col;vis[u]=0;
while(S.top()!=u){
co[S.top()]=col;vis[S.top()]=0;
S.pop();
}
S.pop();
}
}
int main(){
// freopen("tt.in","r",stdin),freopen("tt.out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>p>>M>>m;
memset(head,-1,sizeof(head));
for(int i=1,x,y;i<=n;i++)cin>>x>>y,add(x+p,y),add(y+p,x);
for(int i=1;i<M;i++)add(2*p+i+1,2*p+i),add(2*p+M+i,2*p+M+i+1);
for(int i=1;i<=p;i++){
cin>>l[i]>>r[i];
add(i,2*p+l[i]),add(i,2*p+M+r[i]);
if(r[i]<M)add(2*p+r[i]+1,i+p);
if(l[i]>1)add(2*p+M+l[i]-1,i+p);
}
for(int i=1,u,v;i<=m;i++)cin>>u>>v,add(u,v+p),add(v,u+p);//cout<<u<<" "<<v<<endl;
for(int i=1;i<=2*p+2*M;i++)if(!dfn[i])tarjan(i);
for(int i=1;i<=p;i++)if(co[i]==co[i+p]){cout<<-1<<endl;return 0;}
vector<int>ans;int lim=0;
for(int i=1;i<=p;i++)if(co[i]<co[i+p])ans.push_back(i),lim=max(lim,l[i]);
cout<<ans.size()<<" "<<lim<<endl;
for(auto i:ans)cout<<i<<" ";cout<<endl;
return 0;
}