边的储存
struct edge
{
int v;
int next;
} edges[maxn*maxn];
int last[maxn];
int tot;
void add(int u,int v)
{
edges[tot].v = v;
edges[tot].next = last[u];
last[u] = tot++;
return ;
}
int dfn[maxn],low[maxn]; //时间戳 最早能回溯到的祖先位置。
int color[maxn]; //所属连通分量编号
bool instack[maxn];
int st[maxn],top; //模拟栈
int cnt,scnt; //时间和连通分量计数
Tarjan算法部分:
void tarjan(int u)
{
int x;
dfn[u]=low[u]=cnt++;
st[++top]=u;
instack[u]=1;
for (int j=last[u];j!=-1;j=edges[j].next)
{
int v = edges[j].v;
if (dfn[v]==-1)
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instack[v]) low[u]=min(low[u],dfn[v]);
}
if (dfn[u]==low[u]) //以u为根节点的树形成一个连通分量
{
do
{
x=st[top--];
instack[x]=0;
color[x]=scnt;
}
while (x!=u);
scnt++;
}
return ;
}
solv()函数部分:
void solve()
{
cnt=0;
scnt=0;
top=0;
memset(dfn,-1,sizeof(dfn));
memset(instack,0,sizeof(instack));
for(int i=0; i<n*2; i++)
if (dfn[i]==-1)
{
tarjan(i);
}
return ;
}
2—SAT中判断是否形成自环check()
bool check()
{
for (int i=0; i<n; i++)
if (color[i]==color[i+n])
return 0;
return 1;
}
求出连通分量的解。待定。