复习一下2-SAT姿势(退役那年day2T1就是2-SAT,好像我挂了10分…
2-SAT问题:每个变量取值0/1,求一组变量取值满足一些约束关系。做法是每个变量 x x x开两个点 x 1 x1 x1和 x 0 x0 x0,表示变量 x x x选0/1。根据约束关系连边,有向边 ( a , b ) (a,b) (a,b)表示满足了 a a a就必须满足 b b b。跑一遍Tarjan,如果存在 x x x,使得 x 0 x0 x0和 x 1 x1 x1属于同一个强联通分量,则无解。否则对每个变量 x x x, x 0 x0 x0所属scc编号小则取0,否则取1,就是一组合法解。
关系举例:
x
x
x和
y
y
y至少选一个:
(
x
0
,
y
1
)
,
(
y
0
,
x
1
)
(x0,y1),(y0,x1)
(x0,y1),(y0,x1)
x
x
x和
y
y
y不能同时选:
(
x
1
,
y
0
)
,
(
y
1
,
x
0
)
(x1,y0),(y1,x0)
(x1,y0),(y1,x0)
选了
x
x
x就必须选
y
y
y:
(
x
1
,
y
1
)
,
(
y
0
,
x
0
)
(x1,y1),(y0,x0)
(x1,y1),(y0,x0)
总之对于
x
,
y
x,y
x,y的二元关系,对
x
0
,
y
0
,
x
1
,
y
1
x0,y0,x1,y1
x0,y0,x1,y1四个变量逐一考虑,看选了一个之后是不是有另一个必须选,有就连边。单变量的话,比如
x
x
x必须选,那就是
(
x
0
,
x
1
)
(x0,x1)
(x0,x1)。
【P.S:有向图tarjan里做low[x]=min(low[x],dfn[y])需要判断y在栈内…无向图不用…我一开始忘记了qwq】
回到这道题,若没有 f f f的限制就会是一个裸的2-SAT。考虑 f f f的限制,我们添加 M M M个变量,第 i i i个变量表示 [ f > = i ] [f>=i] [f>=i]。那么对于一个基站 x x x及其频率 [ L , R ] [L,R] [L,R],选择 x x x就必须 [ f > = L ] [f>=L] [f>=L]取1且 [ f > = ( R + 1 ) ] [f>=(R+1)] [f>=(R+1)]取0;同时对于这 M M M个变量之间也存在限制,若 [ f > = L + 1 ] [f>=L+1] [f>=L+1]取1,则 [ f > = L ] [f>=L] [f>=L]必须取1。这个限制关系会传递下去,所以对于 [ f > = L + 1 ] [f>=L+1] [f>=L+1]不需要考虑所有 [ f > = w ] , w < = L [f>=w],w<=L [f>=w],w<=L,只需要考虑与 [ f > = L ] [f>=L] [f>=L]之间的限制关系即可。总复杂度仍然保持线性。
#define no(x) ((x)+n)
#define val(v) (sn+(v))
const int N=2000005;
int A,sn,sp,B,n;
vector<int>S[N];
void E(int x,int y) {S[x].push_back(y);}
int num[N],low[N],scc[N],st[N],cnt,top,inc;bool in[N];
void DFS(int x)
{
num[x]=low[x]=++cnt;
st[++top]=x;in[x]=1;
for(auto &y:S[x])
{
if(!num[y]) DFS(y),low[x]=min(low[x],low[y]);
else if(in[y]) low[x]=min(low[x],num[y]);
}
if(num[x]==low[x])
{
scc[x]=++inc;
while(st[top]!=x) scc[st[top]]=inc,in[st[top]]=0,top--;
top--;in[x]=0;
}
}
int ans[N],u,f;
void _SAT( )
{
int i,x,y,tot=n*2;
for(i=1;i<=tot;i++)
if(!num[i]) DFS(i);
for(i=1;i<=sn;i++)
{
x=scc[i];y=scc[no(i)];
if(x==y) {puts("-1");return;}
if(x<y) ans[++u]=i;
}
for(i=1;i<=sp;i++)
{
x=scc[val(i)];y=scc[no(val(i))];
if(x==y) {puts("-1");return;}
if(x<y) f=i;
}
printf("%d %d\n",u,f);
for(i=1;i<=u;i++) printf("%d ",ans[i]);
}
int main( )
{
read(A);read(sn);read(sp);read(B);n=sn+sp;
int i,j,x,y,l,r;
for(i=1;i<=A;i++)
{
read(x),read(y);
E(no(x),y),E(no(y),x); //x和y必须选至少一个
}
for(x=1;x<=sn;x++)
{
read(l),read(r),r++;
E(x,val(l)),E(no(val(l)),no(x)); //选x必须选f>=l
if(r<=sp) E(x,no(val(r))),E(val(r),no(x)); //选x则不能选f>=(r+1)
}
for(i=1;i<=B;i++)
{
read(x);read(y);
E(x,no(y));E(y,no(x)); //x和y不能同时选
}
for(i=1;i<sp;i++)
{
l=val(i);r=val(i+1);
E(r,l);E(no(l),no(r)); //选f>=l+1必须选f>=l
}
_SAT( );
return 0;
}