zoukankan      html  css  js  c++  java
  • loj 1407(2-sat + 枚举 + 输出一组可行解 )

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27115

    思路:有一个trick要注意:当情况为 2 x y 时,可以推出当y留下时,x也必须留下。然后就是后面的k个限制关系,我们可以3^(k)次方枚举,一旦找到符合条件的就return 。然后就是反向建图,拓扑排序找可行解。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<stack>
      6 #include<queue>
      7 #include<vector>
      8 #include<cmath>
      9 using namespace std;
     10 #define MAXN 2222
     11 
     12 int n,m,k;
     13 struct Node{
     14     int tag;
     15     int num[3];
     16 }node[7];
     17 
     18 vector<vector<int> >g,gg,edge;
     19 
     20 int cnt,bcc_count;
     21 int dfn[MAXN],low[MAXN],color[MAXN];
     22 int degree[MAXN];
     23 bool mark[MAXN];
     24 stack<int>S;
     25 
     26 void Tarjan(int u)
     27 {
     28     low[u]=dfn[u]=++cnt;
     29     mark[u]=true;
     30     S.push(u);
     31     for(int i=0;i<edge[u].size();i++){
     32         int v=edge[u][i];
     33         if(dfn[v]==0){
     34             Tarjan(v);
     35             low[u]=min(low[u],low[v]);
     36         }else if(mark[v]){
     37             low[u]=min(low[u],dfn[v]);
     38         }
     39     }
     40     if(low[u]==dfn[u]){
     41         int v;
     42         bcc_count++;
     43         do{
     44             v=S.top();
     45             S.pop();
     46             mark[v]=false;
     47             color[v]=bcc_count;
     48         }while(u!=v);
     49     }
     50 }
     51 
     52 int opp[MAXN];
     53 bool Check()
     54 {
     55     for(int i=1;i<=n;i++){
     56         if(color[i]==color[i+n])return false;
     57         opp[color[i]]=color[i+n];
     58         opp[color[i+n]]=color[i];
     59     }
     60     return true;
     61 }
     62 
     63 bool Judge()
     64 {
     65     int kk=(int)pow(3.0,k);
     66     for(int i=0;i<kk;i++){
     67         for(int j=1;j<=2*n;j++)edge[j]=g[j];
     68         int j=i,_count=0;
     69         while(_count<k){
     70             int id=j%3;
     71             int x=node[_count].num[id];
     72             if(node[_count].tag==1){
     73                 edge[x+n].push_back(x);
     74             }else 
     75                 edge[x].push_back(x+n);
     76             _count++;
     77             j/=3;
     78         }
     79         cnt=bcc_count=0;
     80         memset(dfn,0,sizeof(dfn));
     81         memset(mark,false,sizeof(mark));
     82         for(int j=1;j<=2*n;j++)if(dfn[j]==0)Tarjan(j);
     83         if(Check())return true;
     84     }
     85     return false;
     86 }
     87 
     88 int vis[MAXN];
     89 void TopSort()
     90 {
     91     queue<int>que;
     92     for(int i=1;i<=bcc_count;i++){
     93         if(degree[i]==0)que.push(i);
     94     }
     95     memset(vis,0,sizeof(vis));
     96     while(!que.empty()){
     97         int u=que.front();
     98         que.pop();
     99         if(vis[u]==0){
    100             vis[u]=1;
    101             vis[opp[u]]=-1;
    102         }
    103         for(int i=0;i<gg[u].size();i++){
    104             int v=gg[u][i];
    105             if(--degree[v]==0)que.push(v);
    106         }
    107     }
    108 }
    109 
    110 vector<int>ans;
    111 void Solve()
    112 {
    113     gg.clear();
    114     gg.resize(2*n+2);
    115     memset(degree,0,sizeof(degree));
    116     for(int u=1;u<=2*n;u++){
    117         for(int i=0;i<edge[u].size();i++){
    118             int v=edge[u][i];
    119             if(color[u]!=color[v]){
    120                 gg[color[v]].push_back(color[u]);
    121                 degree[color[u]]++;
    122             }
    123         }
    124     }
    125     TopSort();
    126     ans.clear();
    127     for(int i=1;i<=n;i++)
    128         if(vis[color[i]]==1)ans.push_back(i);
    129     printf("%d",(int)ans.size());
    130     for(int i=0;i<(int)ans.size();i++){
    131         printf(" %d",ans[i]);
    132     }
    133     puts(".");
    134 }
    135 
    136 int main()
    137 {
    138     int _case,x,y,z,tag,t=1;
    139     scanf("%d",&_case);
    140     while(_case--){
    141         scanf("%d%d%d",&n,&m,&k);
    142         g.clear();
    143         g.resize(2*n+2);
    144         edge.clear();
    145         edge.resize(2*n+2);
    146         while(m--){
    147             scanf("%d%d%d",&tag,&x,&y);
    148             if(tag==1)g[x+n].push_back(y),g[y+n].push_back(x);
    149             else if(tag==2)g[x+n].push_back(y+n),g[y].push_back(x);
    150             else if(tag==3)g[x].push_back(y+n),g[y].push_back(x+n);
    151             else g[x].push_back(y+n),g[y].push_back(x+n),g[x+n].push_back(y),g[y+n].push_back(x);
    152         }
    153         for(int i=0;i<k;i++){
    154             scanf("%d%d%d%d",&node[i].tag,&node[i].num[0],&node[i].num[1],&node[i].num[2]);
    155         }
    156         printf("Case %d: ",t++);
    157         if(Judge()){
    158             printf("Possible ");
    159             Solve();
    160         }else 
    161             puts("Impossible.");
    162     }
    163     return 0;
    164 }
    165         
    View Code
  • 相关阅读:
    hdu 5446 Unknown Treasure lucas和CRT
    Hdu 5444 Elven Postman dfs
    hdu 5443 The Water Problem 线段树
    hdu 5442 Favorite Donut 后缀数组
    hdu 5441 Travel 离线带权并查集
    hdu 5438 Ponds 拓扑排序
    hdu 5437 Alisha’s Party 优先队列
    HDU 5433 Xiao Ming climbing dp
    hdu 5432 Pyramid Split 二分
    Codeforces Round #319 (Div. 1) B. Invariance of Tree 构造
  • 原文地址:https://www.cnblogs.com/wally/p/3337535.html
Copyright © 2011-2022 走看看