03年的论文题
《伍昱--由对称性解2-SAT问题》
突然发现我以前写的2-SAT原来是O(nm)的(lrj书上并没有提到复杂度)
然后就学会了O(m+n)的2-SAT,不过有个很坑爹的地方就是这个算法不能求字典序最小的方案。
#include<iostream> #include<cstdio> #include<cstring> #include<stack> #include<queue> #include<vector> using namespace std; struct Edge{int to,next,v;}e[200005]; int head[16005],cnt; void ins(int u,int v){ e[++cnt]=(Edge){v,head[u]};head[u]=cnt; } int pr[16005],n,m; int sccno[16005],scc_cnt,dfs_clock,pre[16005],lowlink[16005]; stack<int>s; vector<int>g[16005]; void tarjan(int u){ lowlink[u]=pre[u]=++dfs_clock; s.push(u); for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(!pre[v]){ tarjan(v); lowlink[u]=min(lowlink[u],lowlink[v]); }else if(!sccno[v])lowlink[u]=min(lowlink[u],pre[v]); } if(lowlink[u]==pre[u]){ scc_cnt++; while(true){ int x=s.top();s.pop(); sccno[x]=scc_cnt; if(x==u)break; } } } void find_scc(){ for(int i=1;i<=2*n;i++)if(!pre[i])tarjan(i); } int du[16005]; void change(){ for(int i=1;i<=scc_cnt;i++)g[i].clear(); for(int u=1;u<=2*n;u++) for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(sccno[u]!=sccno[v]) g[sccno[v]].push_back(sccno[u]), du[sccno[u]]++; } } int color[16005]; void toposort(){ queue<int>q; for(int i=1;i<=scc_cnt;i++) if(!du[i])q.push(i); while(!q.empty()){ int u=q.front();q.pop(); if(!color[u])color[u]=1,color[pr[u]]=2; for(int i=0;i<g[u].size();i++){ int v=g[u][i]; du[v]--; if(!du[v])q.push(v); } } } void init(){ memset(head,0,sizeof(head));cnt=0; memset(sccno,0,sizeof(sccno)); memset(lowlink,0,sizeof(lowlink)); memset(pre,0,sizeof(pre)); dfs_clock=scc_cnt=0; while(!s.empty())s.pop(); memset(du,0,sizeof(du)); memset(color,0,sizeof(color)); } void solve(){ find_scc(); for(int i=1;i<=2*n;i+=2) if(sccno[i]==sccno[i+1]){ printf("NIE\n"); return; }else pr[sccno[i]]=sccno[i+1],pr[sccno[i+1]]=sccno[i]; change(); toposort(); for(int i=1;i<=2*n;i+=2) if(color[sccno[i]]==1)printf("%d\n",i); else printf("%d\n",i+1); } int main(){ //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); while(~scanf("%d%d",&n,&m)){ init(); int u,v; for(int i=1;i<=m;i++){ scanf("%d%d",&u,&v); ins(u,((v-1)^1)+1); ins(v,((u-1)^1)+1); } solve(); } return 0; }