蒟蒻没去参加,今天自己打了一遍
T2思路是 2-SAT,但是挂了,只能过样例一二和自己造的小数据
洛谷上自测:30pts
f[i] 表示当前强连通分量是否需要 U ,如果需要必然是整个强连通分量都需要,故乘上 size ,最后除以二是因为每个变量有两个对应节点
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,dfn[N<<1],low[N<<1],sta[N<<2],insta[N<<1],cnt,tot,c,t,sz[N<<1],top,id[N<<1],f[N<<1];
char val[N];
vector<int>v[N<<1],g[N<<1];
struct node{
int op,num;
}p[N];
void tarjan(int u)
{
// cout<<u<<endl;
dfn[u]=low[u]=++cnt;
sta[++top]=u,insta[u]=1;
for(int t:v[u])
{
if(!dfn[t])
{
tarjan(t);
low[u]=min(low[u],low[t]);
}
else if(insta[t])low[u]=min(low[u],dfn[t]);
}
if(dfn[u]==low[u])
{
id[u]=++tot;
sz[tot]=1;
// cout<<u<<" ";
while(sta[top]!=u)
{
int tmp=sta[top];
id[tmp]=tot;
insta[tmp]=0;
sz[tot]++;
top--;
// cout<<tmp<<" ";
}
top--;
insta[u]=0;
// cout<<endl;
}
return;
}
void reset()
{
for(int i=1;i<=tot;i++)sz[i]=0,g[i].clear(),f[i]=0;
for(int i=1;i<=n*2;i++)v[i].clear(),dfn[i]=low[i]=0;
for(int i=1;i<=n;i++)val[i]='\0',p[i].op=p[i].num=0;
top=cnt=tot=0;
return;
}
void add(int x,int y)
{
v[x].push_back(y);
return;
}
char rever(char ch)
{
if(ch=='T')return 'F';
if(ch=='F')return 'T';
return ch;
}
int get1(int x)
{
if(x>n)return x-n;
return x;
}
void dfs(int now)
{
for(int t:g[now])
{
f[t]=1;
dfs(t);
}
return;
}
int main()
{
clock_t c1=clock();
freopen("tribool.in","r",stdin);
freopen("tribool.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>c>>t;
while(t--)
{
cin>>n>>m;
int ans=0;
for(int x=1;x<=m;x++)
{
char op;int i,j;
cin>>op>>i;
if(op=='-'||op=='+')cin>>j;
if(op=='-')
{
p[i].op=-1,p[i].num=j;
val[i]=rever(val[j]);
}
else if(op=='+')
{
p[i].op=1,p[i].num=j;
val[i]=val[j];
}
else
{
val[i]=op;
p[i].op=0;
}
}
for(int i=1;i<=n;i++)
{
int op=p[i].op,j=p[i].num;
if(op==1)
{
if(i==j)continue;
if(val[j]=='T')
{
add(j,i);
}
else if(val[j]=='F')
{
add(j+n,i+n);
}
else
{
//jT->iT
add(j,i);
//jF->iF
add(j+n,i+n);
}
}
else
{
if(op==0)continue;
if(val[j]=='T')
{
add(j,i+n);
}
else if(val[j]=='F')
{
add(j+n,i);
}
else
{
//jT->iF
add(j,i+n);
//jF->iT
add(j+n,i);
}
}
}
for(int i=1;i<=n;i++)
if(val[i]=='U')
{
add(i,i+n),add(i+n,i);
// dfs(i);
}
for(int i=1;i<=n*2;i++)
if(!dfn[i])tarjan(i);
for(int i=1;i<=n;i++)
{
if(id[i]==id[i+n])
{
f[id[i]]=1;
}
}
for(int i=1;i<=n*2;i++)
for(int t:v[i])
{
if(id[t]!=id[i])
{
g[id[i]].push_back(id[t]);
}
}
for(int i=1;i<=tot;i++)
{
if(f[i])
dfs(i);
}
for(int i=1;i<=tot;i++)
ans+=f[i]*sz[i];
cout<<ans/2<<endl;
reset();
}
#ifdef LOCAL
cerr<<"Time used:"<<clock()-c1<<"ms"<<endl;
#endif
return 0;
}