zoukankan      html  css  js  c++  java
  • 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’ 。

    精简版

      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 }
    View Code
      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 }
    View Code

    Party http://acm.hdu.edu.cn/showproblem.php?pid=3062

    根据矛盾关系建图,一对夫妻正好是2sat中的a 和 a‘ 点

    精简版

      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 }
    View Code
      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 }
    View Code

    D. Ring Road 2 http://codeforces.com/problemset/problem/27/D

    对m条边 ,每条边不是里面就是外面 ,所以就是2sat的 a 和 a’ ,然后枚举两条边,如果相交,那 i 在里面时 必须 j 在外面。

      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
    ",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 }
    View Code

    end

  • 相关阅读:
    [再寄小读者之数学篇](2014-05-27 偏导数的计算)
    [再寄小读者之数学篇](2014-05-27 积分估计)
    [再寄小读者之数学篇](2014-05-27 二阶矩阵的不等式)
    [再寄小读者之数学篇](2014-05-27 特征值估计)
    [家里蹲大学数学杂志]第039期高等数学习题集
    [家里蹲大学数学杂志]第038期历史上最伟大的10个方程
    [家里蹲大学数学杂志]第037期泛函分析期末试题
    [再寄小读者之数学篇](2014-05-26 计算行列式)
    [家里蹲大学数学杂志]第036期泛函分析期末试题
    [再寄小读者之数学篇](2014-05-25 矩阵的交换子)
  • 原文地址:https://www.cnblogs.com/gaolzzxin/p/3966260.html
Copyright © 2011-2022 走看看