D36 2-SAT P5782 [POI2001] 和平委员会
视频链接:D36 2-SAT P5782 [POI2001] 和平委员会_哔哩哔哩_bilibili
P5782 [POI2001] 和平委员会 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
// 2-SAT+tarjan O(n+m) #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N=16005; int n,m; int head[N],idx; struct Edge{int to,ne;}e[40005]; int dfn[N],low[N],tim,stk[N],top,scc[N],cnt; 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 get(int x){ //x的同党 return (x%2)?x+1:x-1; } int main(){ scanf("%d%d",&n,&m); while(m--){ int a,b; scanf("%d%d",&a,&b); add(a,get(b)); add(b,get(a)); } for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=2*n;i+=2) if(scc[i]==scc[i+1]){ puts("NIE"); return 0; } for(int i=1;i<=2*n;i+=2) if(scc[i]<scc[i+1]) printf("%d\n",i); else printf("%d\n",i+1); }
板子题:Problem - 3062 (hdu.edu.cn)
// 2-SAT+tarjan O(n+m) #include <iostream> #include <cstring> #include <algorithm> using namespace std; #define N 2005 int n,m; int dfn[N],low[N],tim,stk[N],top,scc[N],cnt; int idx,head[N]; struct Edge{ int to,ne; }e[4000005]; void add(int x,int y){ e[++idx].to=y; e[idx].ne=head[x]; head[x]=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(){ while(~scanf("%d%d",&n,&m)){ tim=top=cnt=idx=0; memset(head,0,sizeof head); memset(dfn,0,sizeof dfn); memset(stk,0,sizeof stk); memset(scc,0,sizeof scc); while(m--){ int i,j,a,b; scanf("%d%d%d%d",&i,&j,&a,&b); add(i+a*n,j+!b*n); add(j+b*n,i+!a*n); } for(int i=0; i<2*n; i++) if(!dfn[i]) tarjan(i); bool flag=0; for(int i=0;i<n;i++) if(scc[i]==scc[i+n]){ flag=1;break; } flag?puts("NO"):puts("YES"); } }
// 2-SAT+tarjan O(n+m) #include <iostream> #include <cstring> #include <algorithm> using namespace std; #define N 2005 int n,m; int dfn[N],low[N],tim,stk[N],top,scc[N],cnt; int idx,head[N]; struct Edge{ int to,ne; }e[4000005]; void add(int x,int y){ e[++idx].to=y; e[idx].ne=head[x]; head[x]=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(){ while(~scanf("%d%d",&n,&m)){ tim=top=cnt=idx=0; memset(head,0,sizeof head); memset(dfn,0,sizeof dfn); memset(stk,0,sizeof stk); memset(scc,0,sizeof scc); while(m--){ int i,j,a,b; scanf("%d%d%d%d",&i,&j,&a,&b); add(2*i+a,2*j+!b); //2i妻 2i+1夫 add(2*j+b,2*i+!a); } for(int i=0; i<2*n; i++) if(!dfn[i]) tarjan(i); bool flag=0; for(int i=0;i<2*n;i+=2) if(scc[i]==scc[i+1]){ flag=1;break; } flag?puts("NO"):puts("YES"); } }
分类:
D 图论
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!