题目链接:http://codeforces.com/problemset/problem/27/D
题目大意:
有n个城市,1->2->3->...->n->1,形成一个环,现在要添加m条给定的路,路可以建设在环内或环外,求如何建设可以使得新的路两两不相交(端点除外)。
题目思路:
还是比较裸的2-sat的题目,不过时隔近一年没接触图论了,第一反应还是没想到2-sat。
每一条新路拆成两个点,一个点表示建在内部(i表示),一个点表示建在外部(~i表示)。
如何路A和路B冲突,即不能在同一方向。
则可以建 A->~B,B->~A,~A->B,~B->A四条边。
之后Tarjan跑一遍看是否会冲突。
不冲突再缩点反向topo一遍求方案。
代码:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll __int64
#define ls rt<<1
#define rs ls|1
#define lson l,mid,ls
#define rson mid+1,r,rs
#define middle (l+r)>>1
#define clr_all(x,c) memset(x,c,sizeof(x))
#define clr(x,c,n) memset(x,c,sizeof(x[0])*(n+1))
#define eps (1e-8)
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define PI (acos(-1.0))
#pragma comment(linker, "/STACK:102400000,102400000")
template <class T> T _max(T x,T y){return x>y? x:y;}
template <class T> T _min(T x,T y){return x<y? x:y;}
template <class T> T _abs(T x){return (x < 0)? -x:x;}
template <class T> T _mod(T x,T y){return (x > 0)? x%y:((x%y)+y)%y;}
template <class T> void _swap(T &x,T &y){T t=x;x=y;y=t;}
template <class T> void getmax(T& x,T y){x=(y > x)? y:x;}
template <class T> void getmin(T& x,T y){x=(x<0 || y<x)? y:x;}
int TS,cas=1;
const int M=100+5;
int n,m;
struct edge{
int u,v;
void read(){
scanf("%d%d",&u,&v);
if(u>v) _swap(u,v);
}
}p[M];
bool isIntersect(int l1,int r1,int l2,int r2){
if(l1<l2 && l2<r1 && r1<r2) return true;
if(l2<l1 && l1<r2 && r2<r1) return true;
return false;
}
vector<int>init[M<<1],now[M<<1];
int pre[M<<1],low[M<<1],idx[M<<1];
int ss[M<<1],top,index,nn;
int deg[M<<1],op[M<<1];
void dfs(int u){
ss[++top]=u;
pre[u]=low[u]=++index;
for(int i=0;i<init[u].size();i++){
int v=init[u][i];
if(pre[v]==-1){
dfs(v);
getmin(low[u],low[v]);
}else if(idx[v]==-1){
getmin(low[u],pre[v]);
}
}
if(pre[u]==low[u]){
now[++nn].clear();
int v=-1;
while(u!=v){
idx[v=ss[top--]]=nn;
}
}
}
void Tarjan(int n){
ss[top=index=nn=0]=-1;
clr(pre,-1,n+1),clr(idx,-1,n+1);
for(int i=1;i<=n;i++){
if(pre[i]==-1) dfs(i);
}
}
void shrink(int n){
clr(deg,0,n+1);
for(int u=1;u<=n;u++){
for(int i=0;i<init[u].size();i++){
int v=init[u][i];
if(idx[v]!=idx[u]){
now[idx[u]].push_back(idx[v]);
deg[idx[v]]++;
}
}
}
}
void run(){
int i,j;
for(i=1;i<=m;i++) p[i].read();
for(i=1;i<=m*2;i++) init[i].clear();
bool flag=true;
for(i=1;i<=m;i++){
for(j=i+1;j<=m;j++){
if(isIntersect(p[i].u,p[i].v,p[j].u,p[j].v)){
init[i].push_back(j+m);
init[j+m].push_back(i);
init[j].push_back(i+m);
init[i+m].push_back(j);
}
}
}
Tarjan(m<<1);
for(i=1;i<=m;i++){
if(idx[i]==idx[i+m]){
puts("Impossible");
return;
}
}
shrink(nn);
for(i=1;i<=m;i++){
op[idx[i]]=idx[i+m];
op[idx[i+m]]=idx[i];
}
ss[top=0]=-1;
for(i=1;i<=nn;i++) if(!deg[i]){
ss[++top]=idx[i];
deg[idx[i]]=-1,deg[op[idx[i]]]=-2;
}
while(top){
int u=ss[top--];
for(i=0;i<now[u].size();i++){
int v=now[u][i];
if(--deg[v]==0) ss[++top]=v,deg[v]=-1,deg[op[v]]=-2;
}
}
for(i=1;i<=m;i++){
if(deg[idx[i]]==-1) putchar('o');
else putchar('i');
}puts("");
}
void preSof(){
}
int main(){
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
preSof();
//run();
while((~scanf("%d%d",&n,&m))) run();
//for(scanf("%d",&TS);cas<=TS;cas++) run();
return 0;
}