【2-sat】P5782 [POI2001] 和平委员会
P5782 [POI2001] 和平委员会
大意:n个集合 每个集合有两个点i,i+1 一共2n个点 每个集合选一个点到另一个空集 S 里面 有m个约束条件 i和j不能在一起 求可行的集合S
思路:2-sat 对i j而言 建图(i,j邻居) 和(j,i的邻居),邻居就是他们所属的集合的另一个点 然后判断同同一个集合的两个点是否同时在S里面 输出那个scc[i]小的
#include <cstdio> #include <stack> #include <iostream> #include <cstring> #include <cmath> #include <algorithm> #define ep emplace_back #define ios std::ios::sync_with_stdio(false);std::cin.tie(0); const int N = 4e5+9; using namespace std; int n, m; int head[N], idx = 0; int time__; int low[N], dfn[N]; struct node{ int to, val, next; } e[N<<2]; bool vis[N]; int scc[N], scc_cnt = 0; void add(int u, int v, int val){ e[idx] = {v, val, head[u]}; head[u] = idx++; } int neighbor(int x){ if(x%2==0) return x-1; return x+1; } void bd(){ memset(head, -1, sizeof head); cin >> n >> m; for(int k = 1; k <= m; ++k){ int i,j; cin>>i>>j; //i和j的邻居 //j和i的邻居 add(i , neighbor(j) , 0); add(j , neighbor(i) , 0); } } stack<int> st; void tarjan(int u){ low[u] = dfn[u] = ++time__; st.push(u); vis[u] = 1; for(int i = head[u]; i != -1; i = e[i].next){ int v = e[i].to; if(!dfn[v]){ tarjan(v); low[u] = min(low[u], low[v]); } else if(vis[v]){ low[u] = min(low[u], dfn[v]); } } if(dfn[u] == low[u]){ scc_cnt++; while(true){ int v = st.top(); st.pop(); vis[v] = 0; scc[v] = scc_cnt; if(u == v) break; } } } void solve(){ bd(); for(int i = 1; i <= 2 * n; ++i) if(!dfn[i]) tarjan(i); bool ok = 1; for(int i = 1; i <= 2*n; i+=2){ if(scc[i] == scc[neighbor(i)]){ ok = 0; break; } } if(ok){ for(int i=1 ; i<=2*n ; i+=2){ cout<<(scc[i] < scc[i+1] ? i:i+1); cout<<"\n"; } } else cout<<"NIE"; } int main(){ ios; solve(); return 0; }
分类:
图论 / 图论的练习题
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具