标签:script false line main 包含 ring div tar lib
2-sat问题的模板题目,先说2-sat问题的基本解法:
一些问题可以转成布尔方程来求解····
我们的目的是将其布尔方程的每个文字拆开成两点,一点表示其本身,一点表示它的非,比如a就拆成a与┐a,并且将各种运算符号转化为只含有^(与)和->(A->B表示A为真则B为真)的形式,比如∨转化为┐a -> b ^ ┐b -> a ,a一定为真就转换为 ┐a->a 的形式,然后将->转换成边,两边连上对应的点。
如果a与┐a在最后建成的图的同一个强连通分量里···那么布尔方程有解
如果a所在强连通分量的拓扑序在┐a所在强连通分量的拓扑序之后,那么a为真,之前a为假,如果相等则真假均可以取。这里求拓扑序直接用tarjian即可,先找到的强连通分量的拓扑序一定更大
以上就是基本知识
但这道题有点特殊·····因为包含a拓扑序与┐a相等的情况要判断····用tarjian的话有点麻烦···
但n很小···直接dfs即可····若a可以到达┐a,则说明a可能与┐a在同一强连通分量或者a所在强连通分量的拓扑序小于等于┐a的拓扑序
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<cstring> #include<string> #include<algorithm> using namespace std; const int N=2005; const int M=10005; int first[N],next[M],go[M],tot=1,n,m; bool visit[N]; inline void comb(int a,int b) { next[++tot]=first[a],first[a]=tot,go[tot]=b; } inline int tran(int a) { return (a%2==1)?a+1:a-1; } inline int R() { char c; int f=0; for(c=getchar();c<‘0‘||c>‘9‘;c=getchar()); for(;c<=‘9‘&&c>=‘0‘;c=getchar()) f=(f<<3)+(f<<1)+c-‘0‘; return f; } inline void dfs(int u) { visit[u]=true; for(int e=first[u];e;e=next[e]) { if(!visit[go[e]]) dfs(go[e]); } } inline bool jud(int u) { memset(visit,false,sizeof(visit)); dfs(u); if(!visit[tran(u)]) return true; else return false; } int main() { //freopen("a.in","r",stdin); n=R(),m=R(); char s[5],t[5]; int a,b; for(int i=1;i<=m;i++) { scanf("%d%s%d%s",&a,s,&b,t); int t1,t2; if(s[0]==‘Y‘) t1=a*2-1; else t1=a*2; if(t[0]==‘Y‘) t2=b*2-1; else t2=b*2; comb(tran(t2),t1); comb(tran(t1),t2); } for(int i=1;i<=n;i++) { bool flag1=jud(i*2-1); bool flag2=jud(i*2); if(!flag1&&!flag2) {cout<<"IMPOSSIBLE"<<endl;return 0;} else if(!flag1) cout<<"N"; else if(!flag2) cout<<"Y"; else cout<<"?"; } return 0; }
标签:script false line main 包含 ring div tar lib
原文地址:http://www.cnblogs.com/AseanA/p/7476747.html