2-sat
Let's go home http://acm.hdu.edu.cn/showproblem.php?pid=1824
把队长看成 a 点 把两个队员看成同一个点 a‘ ,a的对称点, 也就是 非a。 这个是2sat的点。 然后再根据输入 a b 那么 a要和b的对称点连边
b要和a的对称点连边,因为题目中说的选了a ,b就不选,那就是选a就必须选 非b ,就是b’ 。
精简版
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<stack> 5 #define mt(a,b) memset(a,b,sizeof(a)) 6 using namespace std; 7 class TwoSat { ///2-sat判定,solve函数返回是否有解,i结点的对称结点i^为i+n, 8 static const int ME=10010;///边的个数 9 static const int MV=4010;///点的个数 10 struct G { 11 struct E { 12 int u,v,next; 13 } e[ME]; 14 int le,head[MV]; 15 void init() { 16 le=0; 17 mt(head,-1); 18 } 19 void add(int u,int v) { 20 e[le].u=u; 21 e[le].v=v; 22 e[le].next=head[u]; 23 head[u]=le++; 24 } 25 } g; 26 class Tarjan { ///有向图强连通分量缩点o(MV+ME) 27 int Index,Bcnt,num[MV],belong[MV],dfn[MV],low[MV]; 28 bool instack[MV]; 29 stack<int> s; 30 void tarjan(int u) { 31 dfn[u]=low[u]=++Index; 32 instack[u]=true; 33 s.push(u); 34 int v; 35 for(int i=g.head[u]; ~i; i=g.e[i].next) { 36 v=g.e[i].v; 37 if(!dfn[v]) { 38 tarjan(v); 39 low[u]=min(low[u],low[v]); 40 } else if(instack[v]) { 41 low[u]=min(low[u],dfn[v]); 42 } 43 } 44 if(dfn[u]==low[u]) { 45 Bcnt++; 46 do { 47 v=s.top(); 48 s.pop(); 49 instack[v]=false; 50 belong[v]=Bcnt; 51 num[Bcnt]++; 52 } while(u!=v); 53 } 54 } 55 public: 56 G g; 57 void init() { 58 g.init(); 59 Index=Bcnt=0; 60 mt(num,0); 61 mt(dfn,0); 62 mt(low,0); 63 mt(instack,0); 64 while(!s.empty()) s.pop(); 65 } 66 void add(int u,int v) { 67 g.add(u,v); 68 } 69 void solve(int n) {///传入点数,点下标1开始 70 for(int i=1; i<=n; i++) { 71 if(!dfn[i]) { 72 tarjan(i); 73 } 74 } 75 } 76 int getbcnt() {///强连通分量的个数 77 return Bcnt; 78 } 79 int getbelong(int id) {///属于哪个分量,分量下标1开始 80 return belong[id]; 81 } 82 int getnum(int id) {///某个分量的点的个数 83 return num[id]; 84 } 85 } T; 86 int n; 87 public: 88 void init(int tn) { ///传入判定结点2*n 89 n=tn; 90 T.init(); 91 } 92 void add(int u,int v) { ///如果取u必须取v结点添加边u->v,下标1开始 93 T.add(u,v); 94 } 95 bool solve() { 96 T.solve(n); 97 for(int i=1,z=n/2; i<=z; i++) { 98 if(T.getbelong(i)==T.getbelong(i+z))return false; 99 } 100 return true; 101 } 102 } gx; 103 int mp[3010]; 104 int main(){ 105 int n,m,a,b,c; 106 while(~scanf("%d%d",&n,&m)){ 107 for(int i=1;i<=n;i++){ 108 scanf("%d%d%d",&a,&b,&c); 109 mp[a]=i; 110 mp[b]=mp[c]=i+n; 111 } 112 gx.init(2*n); 113 while(m--){ 114 scanf("%d%d",&a,&b); 115 a=mp[a]; 116 b=mp[b]; 117 gx.add(a,b+(b>n?-n:n)); 118 gx.add(b,a+(a>n?-n:n)); 119 } 120 puts(gx.solve()?"yes":"no"); 121 } 122 return 0; 123 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<stack> 5 #include<map> 6 #define mt(a,b) memset(a,b,sizeof(a)) 7 using namespace std; 8 class TwoSat { ///2-sat判定,solve函数返回是否有解,i结点的对称结点i^为i+n, 9 static const int ME=10010;///边的个数 10 static const int MV=2010;///点的个数 11 struct G { 12 struct E { 13 int u,v,next; 14 } e[ME]; 15 int le,head[MV]; 16 void init() { 17 le=0; 18 mt(head,-1); 19 } 20 void add(int u,int v) { 21 e[le].u=u; 22 e[le].v=v; 23 e[le].next=head[u]; 24 head[u]=le++; 25 } 26 } g; 27 class Tarjan { ///有向图强连通分量缩点o(MV+ME) 28 int Index,Bcnt,num[MV],belong[MV],dfn[MV],low[MV]; 29 bool instack[MV]; 30 stack<int> s; 31 void tarjan(int u) { 32 dfn[u]=low[u]=++Index; 33 instack[u]=true; 34 s.push(u); 35 int v; 36 for(int i=g.head[u]; ~i; i=g.e[i].next) { 37 v=g.e[i].v; 38 if(!dfn[v]) { 39 tarjan(v); 40 low[u]=min(low[u],low[v]); 41 } else if(instack[v]) { 42 low[u]=min(low[u],dfn[v]); 43 } 44 } 45 if(dfn[u]==low[u]) { 46 Bcnt++; 47 do { 48 v=s.top(); 49 s.pop(); 50 instack[v]=false; 51 belong[v]=Bcnt; 52 num[Bcnt]++; 53 } while(u!=v); 54 } 55 } 56 public: 57 G g; 58 void init() { 59 g.init(); 60 Index=Bcnt=0; 61 mt(num,0); 62 mt(dfn,0); 63 mt(low,0); 64 mt(instack,0); 65 while(!s.empty()) s.pop(); 66 } 67 void add(int u,int v) { 68 g.add(u,v); 69 } 70 void solve(int n) {///传入点数,点下标1开始 71 for(int i=1; i<=n; i++) { 72 if(!dfn[i]) { 73 tarjan(i); 74 } 75 } 76 } 77 int getbcnt() {///强连通分量的个数 78 return Bcnt; 79 } 80 int getbelong(int id) {///属于哪个分量,分量下标1开始 81 return belong[id]; 82 } 83 int getnum(int id) {///某个分量的点的个数 84 return num[id]; 85 } 86 } T; 87 class Unitenode { ///缩点 88 G ug; 89 int n,in[MV]; 90 bool mat[MV][MV]; 91 queue<int> q; 92 public: 93 void init(int tn) { 94 n=tn; 95 ug.init(); 96 mt(in,0); 97 for(int i=1;i<=n;i++) 98 for(int j=1;j<=n;j++) 99 mat[i][j]=i==j?true:false; 100 } 101 void add(int u,int v) { 102 if(!mat[u][v]) { 103 in[v]++; 104 mat[u][v]=true; 105 ug.add(u,v); 106 } 107 } 108 void solve(int tp[]) { 109 while(!q.empty()) q.pop(); 110 for(int i=1; i<=n; i++) { 111 if(!in[i]) { 112 q.push(i); 113 } 114 } 115 int ret=1; 116 while(!q.empty()) { 117 int u=q.front(); 118 q.pop(); 119 tp[ret++]=u; 120 for(int i=ug.head[u]; ~i; i=ug.e[i].next) { 121 int v=ug.e[i].v; 122 in[v]--; 123 if(!in[v]) { 124 q.push(v); 125 } 126 } 127 } 128 } 129 } U; 130 void unite() { 131 U.init(T.getbcnt()); 132 for(int i=1; i<=n; i++) { 133 for(int j=T.g.head[i]; ~j; j=T.g.e[j].next) { 134 U.add(T.getbelong(i),T.getbelong(T.g.e[j].v)); 135 } 136 } 137 } 138 int n,tp[MV]; 139 bool flag[MV]; 140 public: 141 void init(int tn) { ///传入判定结点2*n 142 n=tn; 143 T.init(); 144 } 145 void add(int u,int v) { ///如果取u必须取v结点添加边u->v,下标1开始 146 T.add(u,v); 147 } 148 bool solve() { 149 T.solve(n); 150 for(int i=1,z=n/2; i<=z; i++) { 151 if(T.getbelong(i)==T.getbelong(i+z))return false; 152 } 153 return true; 154 } 155 void output(bool ans[]) {///ans[i]==false则选择i结点,否则选择i^结点 156 unite(); 157 U.solve(tp); 158 mt(flag,0); 159 for(int i=T.getbcnt(); i>0; i--) { 160 for(int j=1,y; j<=n; j++) { 161 if(j>n/2)y=j-n/2; 162 else y=j; 163 if(!flag[y]&&T.getbelong(j)==tp[i]) { 164 flag[y]=true; 165 if(j>n/2) { 166 ans[j-n/2]=true; 167 } else { 168 ans[j]=false; 169 } 170 } 171 } 172 } 173 } 174 } gx; 175 int mp[3010]; 176 int main() { 177 int n,m,x,y,z; 178 while(~scanf("%d%d",&n,&m)) { 179 gx.init(n*2); 180 int myid=1; 181 for(int i=0; i<n; i++) { 182 scanf("%d%d%d",&x,&y,&z); 183 mp[x]=myid; 184 mp[y]=myid+n; 185 mp[z]=myid+n; 186 myid++; 187 } 188 for(int i=0; i<m; i++) { 189 scanf("%d%d",&x,&y); 190 x=mp[x]; 191 y=mp[y]; 192 gx.add(x,y+(y>n?-n:n)); 193 gx.add(y,x+(x>n?-n:n)); 194 } 195 if(gx.solve()) { 196 puts("yes"); 197 } else { 198 puts("no"); 199 } 200 } 201 return 0; 202 }
Party http://acm.hdu.edu.cn/showproblem.php?pid=3062
根据矛盾关系建图,一对夫妻正好是2sat中的a 和 a‘ 点
精简版
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<stack> 5 #include<map> 6 #define mt(a,b) memset(a,b,sizeof(a)) 7 using namespace std; 8 class TwoSat { ///2-sat判定,solve函数返回是否有解,i结点的对称结点i^为i+n, 9 static const int ME=1600010;///边的个数 10 static const int MV=4010;///点的个数 11 struct G { 12 struct E { 13 int u,v,next; 14 } e[ME]; 15 int le,head[MV]; 16 void init() { 17 le=0; 18 mt(head,-1); 19 } 20 void add(int u,int v) { 21 e[le].u=u; 22 e[le].v=v; 23 e[le].next=head[u]; 24 head[u]=le++; 25 } 26 } g; 27 class Tarjan { ///有向图强连通分量缩点o(MV+ME) 28 int Index,Bcnt,num[MV],belong[MV],dfn[MV],low[MV]; 29 bool instack[MV]; 30 stack<int> s; 31 void tarjan(int u) { 32 dfn[u]=low[u]=++Index; 33 instack[u]=true; 34 s.push(u); 35 int v; 36 for(int i=g.head[u]; ~i; i=g.e[i].next) { 37 v=g.e[i].v; 38 if(!dfn[v]) { 39 tarjan(v); 40 low[u]=min(low[u],low[v]); 41 } else if(instack[v]) { 42 low[u]=min(low[u],dfn[v]); 43 } 44 } 45 if(dfn[u]==low[u]) { 46 Bcnt++; 47 do { 48 v=s.top(); 49 s.pop(); 50 instack[v]=false; 51 belong[v]=Bcnt; 52 num[Bcnt]++; 53 } while(u!=v); 54 } 55 } 56 public: 57 G g; 58 void init() { 59 g.init(); 60 Index=Bcnt=0; 61 mt(num,0); 62 mt(dfn,0); 63 mt(low,0); 64 mt(instack,0); 65 while(!s.empty()) s.pop(); 66 } 67 void add(int u,int v) { 68 g.add(u,v); 69 } 70 void solve(int n) {///传入点数,点下标1开始 71 for(int i=1; i<=n; i++) { 72 if(!dfn[i]) { 73 tarjan(i); 74 } 75 } 76 } 77 int getbcnt() {///强连通分量的个数 78 return Bcnt; 79 } 80 int getbelong(int id) {///属于哪个分量,分量下标1开始 81 return belong[id]; 82 } 83 int getnum(int id) {///某个分量的点的个数 84 return num[id]; 85 } 86 } T; 87 int n; 88 public: 89 void init(int tn) { ///传入判定结点2*n 90 n=tn; 91 T.init(); 92 } 93 void add(int u,int v) { ///如果取u必须取v结点添加边u->v,下标1开始 94 T.add(u,v); 95 } 96 bool solve() { 97 T.solve(n); 98 for(int i=1,z=n/2; i<=z; i++) { 99 if(T.getbelong(i)==T.getbelong(i+z))return false; 100 } 101 return true; 102 } 103 } gx; 104 int n; 105 int getfan(int x){ 106 if(x<=n) return x+n; 107 return x-n; 108 } 109 int main(){ 110 int m,a,b,c,d; 111 while(~scanf("%d%d",&n,&m)){ 112 gx.init(2*n); 113 while(m--){ 114 scanf("%d%d%d%d",&a,&b,&c,&d); 115 a++; 116 b++; 117 a+=c*n; 118 b+=d*n; 119 gx.add(a,getfan(b)); 120 gx.add(b,getfan(a)); 121 } 122 puts(gx.solve()?"YES":"NO"); 123 } 124 return 0; 125 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<stack> 5 #include<map> 6 #define mt(a,b) memset(a,b,sizeof(a)) 7 using namespace std; 8 class TwoSat { ///2-sat判定,solve函数返回是否有解,i结点的对称结点i^为i+n, 9 static const int ME=1000010;///边的个数 10 static const int MV=2010;///点的个数 11 struct G { 12 struct E { 13 int u,v,next; 14 } e[ME]; 15 int le,head[MV]; 16 void init() { 17 le=0; 18 mt(head,-1); 19 } 20 void add(int u,int v) { 21 e[le].u=u; 22 e[le].v=v; 23 e[le].next=head[u]; 24 head[u]=le++; 25 } 26 } g; 27 class Tarjan { ///有向图强连通分量缩点o(MV+ME) 28 int Index,Bcnt,num[MV],belong[MV],dfn[MV],low[MV]; 29 bool instack[MV]; 30 stack<int> s; 31 void tarjan(int u) { 32 dfn[u]=low[u]=++Index; 33 instack[u]=true; 34 s.push(u); 35 int v; 36 for(int i=g.head[u]; ~i; i=g.e[i].next) { 37 v=g.e[i].v; 38 if(!dfn[v]) { 39 tarjan(v); 40 low[u]=min(low[u],low[v]); 41 } else if(instack[v]) { 42 low[u]=min(low[u],dfn[v]); 43 } 44 } 45 if(dfn[u]==low[u]) { 46 Bcnt++; 47 do { 48 v=s.top(); 49 s.pop(); 50 instack[v]=false; 51 belong[v]=Bcnt; 52 num[Bcnt]++; 53 } while(u!=v); 54 } 55 } 56 public: 57 G g; 58 void init() { 59 g.init(); 60 Index=Bcnt=0; 61 mt(num,0); 62 mt(dfn,0); 63 mt(low,0); 64 mt(instack,0); 65 while(!s.empty()) s.pop(); 66 } 67 void add(int u,int v) { 68 g.add(u,v); 69 } 70 void solve(int n) {///传入点数,点下标1开始 71 for(int i=1; i<=n; i++) { 72 if(!dfn[i]) { 73 tarjan(i); 74 } 75 } 76 } 77 int getbcnt() {///强连通分量的个数 78 return Bcnt; 79 } 80 int getbelong(int id) {///属于哪个分量,分量下标1开始 81 return belong[id]; 82 } 83 int getnum(int id) {///某个分量的点的个数 84 return num[id]; 85 } 86 } T; 87 class Unitenode { ///缩点 88 G ug; 89 int n,in[MV]; 90 bool mat[MV][MV]; 91 queue<int> q; 92 public: 93 void init(int tn) { 94 n=tn; 95 ug.init(); 96 mt(in,0); 97 for(int i=1;i<=n;i++) 98 for(int j=1;j<=n;j++) 99 mat[i][j]=i==j?true:false; 100 } 101 void add(int u,int v) { 102 if(!mat[u][v]) { 103 in[v]++; 104 mat[u][v]=true; 105 ug.add(u,v); 106 } 107 } 108 void solve(int tp[]) { 109 while(!q.empty()) q.pop(); 110 for(int i=1; i<=n; i++) { 111 if(!in[i]) { 112 q.push(i); 113 } 114 } 115 int ret=1; 116 while(!q.empty()) { 117 int u=q.front(); 118 q.pop(); 119 tp[ret++]=u; 120 for(int i=ug.head[u]; ~i; i=ug.e[i].next) { 121 int v=ug.e[i].v; 122 in[v]--; 123 if(!in[v]) { 124 q.push(v); 125 } 126 } 127 } 128 } 129 } U; 130 void unite() { 131 U.init(T.getbcnt()); 132 for(int i=1; i<=n; i++) { 133 for(int j=T.g.head[i]; ~j; j=T.g.e[j].next) { 134 U.add(T.getbelong(i),T.getbelong(T.g.e[j].v)); 135 } 136 } 137 } 138 int n,tp[MV]; 139 bool flag[MV]; 140 public: 141 void init(int tn) { ///传入判定结点2*n 142 n=tn; 143 T.init(); 144 } 145 void add(int u,int v) { ///如果取u必须取v结点添加边u->v,下标1开始 146 T.add(u,v); 147 } 148 bool solve() { 149 T.solve(n); 150 for(int i=1,z=n/2; i<=z; i++) { 151 if(T.getbelong(i)==T.getbelong(i+z))return false; 152 } 153 return true; 154 } 155 void output(bool ans[]) {///ans[i]==false则选择i结点,否则选择i^结点 156 unite(); 157 U.solve(tp); 158 mt(flag,0); 159 for(int i=T.getbcnt(); i>0; i--) { 160 for(int j=1,y; j<=n; j++) { 161 if(j>n/2)y=j-n/2; 162 else y=j; 163 if(!flag[y]&&T.getbelong(j)==tp[i]) { 164 flag[y]=true; 165 if(j>n/2) { 166 ans[j-n/2]=true; 167 } else { 168 ans[j]=false; 169 } 170 } 171 } 172 } 173 } 174 } gx; 175 int main() { 176 int n,m,a,b,c,d; 177 while(~scanf("%d%d",&n,&m)) { 178 gx.init(n*2); 179 for(int i=0; i<m; i++) { 180 scanf("%d%d%d%d",&a,&b,&c,&d); 181 a++; 182 b++; 183 if(c==0&&d==0) { 184 gx.add(a,b+n); 185 gx.add(b,a+n); 186 } else if(c==1&&d==1) { 187 gx.add(a+n,b); 188 gx.add(b+n,a); 189 } else if(c==0&&d==1) { 190 gx.add(a,b); 191 gx.add(b+n,a+n); 192 } else if(c==1&&d==0) { 193 gx.add(a+n,b+n); 194 gx.add(b,a); 195 } 196 } 197 if(gx.solve()) { 198 puts("YES"); 199 } else { 200 puts("NO"); 201 } 202 } 203 return 0; 204 }
D. Ring Road 2 http://codeforces.com/problemset/problem/27/D
对m条边 ,每条边不是里面就是外面 ,所以就是2sat的 a 和 a’ ,然后枚举两条边,如果相交,那 i 在里面时 必须 j 在外面。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<stack> 5 #include<map> 6 #define mt(a,b) memset(a,b,sizeof(a)) 7 using namespace std; 8 class TwoSat { ///2-sat判定,solve函数返回是否有解,i结点的对称结点i^为i+n, 9 static const int ME=1000010;///边的个数 10 static const int MV=2010;///点的个数 11 struct G { 12 struct E { 13 int u,v,next; 14 } e[ME]; 15 int le,head[MV]; 16 void init() { 17 le=0; 18 mt(head,-1); 19 } 20 void add(int u,int v) { 21 e[le].u=u; 22 e[le].v=v; 23 e[le].next=head[u]; 24 head[u]=le++; 25 } 26 } g; 27 class Tarjan { ///有向图强连通分量缩点o(MV+ME) 28 int Index,Bcnt,num[MV],belong[MV],dfn[MV],low[MV]; 29 bool instack[MV]; 30 stack<int> s; 31 void tarjan(int u) { 32 dfn[u]=low[u]=++Index; 33 instack[u]=true; 34 s.push(u); 35 int v; 36 for(int i=g.head[u]; ~i; i=g.e[i].next) { 37 v=g.e[i].v; 38 if(!dfn[v]) { 39 tarjan(v); 40 low[u]=min(low[u],low[v]); 41 } else if(instack[v]) { 42 low[u]=min(low[u],dfn[v]); 43 } 44 } 45 if(dfn[u]==low[u]) { 46 Bcnt++; 47 do { 48 v=s.top(); 49 s.pop(); 50 instack[v]=false; 51 belong[v]=Bcnt; 52 num[Bcnt]++; 53 } while(u!=v); 54 } 55 } 56 public: 57 G g; 58 void init() { 59 g.init(); 60 Index=Bcnt=0; 61 mt(num,0); 62 mt(dfn,0); 63 mt(low,0); 64 mt(instack,0); 65 while(!s.empty()) s.pop(); 66 } 67 void add(int u,int v) { 68 g.add(u,v); 69 } 70 void solve(int n) {///传入点数,点下标1开始 71 for(int i=1; i<=n; i++) { 72 if(!dfn[i]) { 73 tarjan(i); 74 } 75 } 76 } 77 int getbcnt() {///强连通分量的个数 78 return Bcnt; 79 } 80 int getbelong(int id) {///属于哪个分量,分量下标1开始 81 return belong[id]; 82 } 83 int getnum(int id) {///某个分量的点的个数 84 return num[id]; 85 } 86 } T; 87 class Unitenode { ///缩点 88 G ug; 89 int n,in[MV]; 90 bool mat[MV][MV]; 91 queue<int> q; 92 public: 93 void init(int tn) { 94 n=tn; 95 ug.init(); 96 mt(in,0); 97 for(int i=1;i<=n;i++) 98 for(int j=1;j<=n;j++) 99 mat[i][j]=i==j?true:false; 100 } 101 void add(int u,int v) { 102 if(!mat[u][v]) { 103 in[v]++; 104 mat[u][v]=true; 105 ug.add(u,v); 106 } 107 } 108 void solve(int tp[]) { 109 while(!q.empty()) q.pop(); 110 for(int i=1; i<=n; i++) { 111 if(!in[i]) { 112 q.push(i); 113 } 114 } 115 int ret=1; 116 while(!q.empty()) { 117 int u=q.front(); 118 q.pop(); 119 tp[ret++]=u; 120 for(int i=ug.head[u]; ~i; i=ug.e[i].next) { 121 int v=ug.e[i].v; 122 in[v]--; 123 if(!in[v]) { 124 q.push(v); 125 } 126 } 127 } 128 } 129 } U; 130 void unite() { 131 U.init(T.getbcnt()); 132 for(int i=1; i<=n; i++) { 133 for(int j=T.g.head[i]; ~j; j=T.g.e[j].next) { 134 U.add(T.getbelong(i),T.getbelong(T.g.e[j].v)); 135 } 136 } 137 } 138 int n,tp[MV]; 139 bool flag[MV]; 140 public: 141 void init(int tn) { ///传入判定结点2*n 142 n=tn; 143 T.init(); 144 } 145 void add(int u,int v) { ///如果取u必须取v结点添加边u->v,下标1开始 146 T.add(u,v); 147 } 148 bool solve() { 149 T.solve(n); 150 for(int i=1,z=n/2; i<=z; i++) { 151 if(T.getbelong(i)==T.getbelong(i+z))return false; 152 } 153 return true; 154 } 155 void output(bool ans[]) {///ans[i]==false则选择i结点,否则选择i^结点 156 unite(); 157 U.solve(tp); 158 mt(flag,0); 159 for(int i=T.getbcnt(); i>0; i--) { 160 for(int j=1,y; j<=n; j++) { 161 if(j>n/2)y=j-n/2; 162 else y=j; 163 if(!flag[y]&&T.getbelong(j)==tp[i]) { 164 flag[y]=true; 165 if(j>n/2) { 166 ans[j-n/2]=true; 167 } else { 168 ans[j]=false; 169 } 170 } 171 } 172 } 173 } 174 } gx; 175 const int M=128; 176 struct IN { 177 int x,y; 178 } in[M]; 179 bool ok(int i,int j) { 180 if(in[i].x<in[j].x&&in[j].x<in[i].y&&in[i].y<in[j].y) return true; 181 return false; 182 } 183 bool judge(int i,int j) { 184 if(ok(i,j)||ok(j,i)) return true; 185 return false; 186 } 187 bool ans[M]; 188 int main() { 189 int n,m; 190 while(~scanf("%d%d",&n,&m)) { 191 gx.init(m*2); 192 for(int i=1; i<=m; i++) { 193 scanf("%d%d",&in[i].x,&in[i].y); 194 if(in[i].x>in[i].y) swap(in[i].x,in[i].y); 195 } 196 for(int i=1; i<=m; i++) { 197 for(int j=i+1; j<=m; j++) { 198 if(judge(i,j)) { 199 // printf("%d %d\n",i,j); 200 gx.add(i,j+m); 201 gx.add(j,i+m); 202 gx.add(i+m,j); 203 gx.add(j+m,i); 204 } 205 } 206 } 207 if(gx.solve()) { 208 gx.output(ans); 209 for(int i=1; i<=m; i++) { 210 if(ans[i]) printf("i"); 211 else printf("o"); 212 } 213 puts(""); 214 } else { 215 puts("Impossible"); 216 } 217 } 218 return 0; 219 }
end