D35【模板】2-SAT
视频链接:D35【模板】2-SAT_哔哩哔哩_bilibili
D14 强连通分量 Tarjan 算法 - 董晓 - 博客园 (cnblogs.com)
P4782 【模板】2-SAT - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
// 2-SAT+tarjan O(n+m) #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N=2000005; int n,m; int head[N],to[N],ne[N],idx; int dfn[N],low[N],tim,stk[N],top,scc[N],cnt; void add(int a,int b){ to[++idx]=b,ne[idx]=head[a],head[a]=idx; } void tarjan(int x){ dfn[x]=low[x]=++tim; stk[++top]=x; for(int i=head[x];i;i=ne[i]){ int y=to[i]; if(!dfn[y]){ //若y尚未访问 tarjan(y); low[x]=min(low[x],low[y]); } else if(!scc[y]) //若y已访问且未处理 low[x]=min(low[x],dfn[y]); } if(low[x]==dfn[x]){ //若x是SCC的根 ++cnt; for(int y=-1;y!=x;) scc[y=stk[top--]]=cnt; } } int main(){ scanf("%d%d",&n,&m); for(int i,a,j,b;m--;){ scanf("%d%d%d%d",&i,&a,&j,&b); add(i+!a*n,j+b*n); //xi拆成i和i+n add(j+!b*n,i+a*n); } for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i); //求SCC for(int i=1;i<=n;i++) if(scc[i]==scc[i+n]){ puts("IMPOSSIBLE"); return 0; } puts("POSSIBLE"); for(int i=1;i<=n;i++) printf("%d ",scc[i]>scc[i+n]); }
// 2-SAT+tarjan O(n+m) #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N=2000005; int n,m; int head[N],to[N],ne[N],idx; int dfn[N],low[N],tim,stk[N],top,scc[N],cnt; void add(int a,int b){ to[++idx]=b,ne[idx]=head[a],head[a]=idx; } void tarjan(int x){ dfn[x]=low[x]=++tim; stk[++top]=x; for(int i=head[x];i;i=ne[i]){ int y=to[i]; if(!dfn[y]){ //若y尚未访问 tarjan(y); low[x]=min(low[x],low[y]); } else if(!scc[y]) //若y已访问且未处理 low[x]=min(low[x],dfn[y]); } if(low[x]==dfn[x]){ //若x是SCC的根 ++cnt; for(int y=-1;y!=x;) scc[y=stk[top--]]=cnt; } } int main(){ scanf("%d%d",&n,&m); for(int i,a,j,b;m--;){ scanf("%d%d%d%d",&i,&a,&j,&b); i--,j--; add(2*i+!a,2*j+b); //xi拆成2i和2i+1 add(2*j+!b,2*i+a); } for(int i=0;i<2*n;i++) if(!dfn[i]) tarjan(i); //求SCC for(int i=0;i<2*n;i+=2) if(scc[i]==scc[i+1]){ puts("IMPOSSIBLE"); return 0; } puts("POSSIBLE"); for(int i=0;i<2*n;i+=2) printf("%d ",scc[i]>scc[i+1]); }
板子题:P4171 [JSOI2010] 满汉全席 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N=205; int t,n,m; int head[N],idx; struct Edge{int to,ne;}e[4005]; int dfn[N],low[N],tim,stk[N],top,scc[N],cnt; char s1[5],s2[5]; void add(int a,int b){ e[++idx].to=b; e[idx].ne=head[a]; head[a]=idx; } void tarjan(int x){ dfn[x]=low[x]=++tim; stk[++top]=x; for(int i=head[x];i;i=e[i].ne){ int y=e[i].to; if(!dfn[y]){ //若y尚未访问 tarjan(y); low[x]=min(low[x],low[y]); } else if(!scc[y]) //若y已访问且未处理 low[x]=min(low[x],dfn[y]); } if(low[x]==dfn[x]){ //若x是SCC的根 ++cnt; for(int y=-1;y!=x;) scc[y=stk[top--]]=cnt; } } int main(){ scanf("%d",&t); while(t--){ idx=tim=cnt=top=0; memset(head,0,sizeof head); memset(dfn,0,sizeof dfn); memset(scc,0,sizeof scc); scanf("%d%d",&n,&m); while(m--){ scanf("%s%s",&s1,&s2); int i=0,j=0,a,b,k; a=(s1[0]=='m'?0:1); b=(s2[0]=='m'?0:1); for(k=1;s1[k]>='0'&&s1[k]<='9';) i=i*10+s1[k++]-'0'; for(k=1;s2[k]>='0'&&s2[k]<='9';) j=j*10+s2[k++]-'0'; add(i+n*!a,j+n*b); add(j+n*!b,i+n*a); } for(int i=1;i<=n<<1;++i)if(!dfn[i])tarjan(i); bool flag=0; for(int i=1;i<=n;++i) if(scc[i]==scc[i+n]){ flag=1; break; } flag?puts("BAD"):puts("GOOD"); } }
分类:
D 图论
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析