首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

CF 27D Ring Road 二

2013-03-27 
CF 27D Ring Road 2题目链接:http://codeforces.com/problemset/problem/27/D题目大意:有n个城市,1-2-3-

CF 27D Ring Road 2

题目链接: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;}


热点排行