• loj 1251(2-sat + 输出一组可行解)


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

    思路:u表示留下,~u表示离开,同理v,对于+u,-v,我们可以这样来定义:若u离开,则v必须留下,如v离开,则u必须留下,于是我们可以连边u+n->v,v+n->u,后面的同理。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<stack>
      6 #include<vector>
      7 #include<queue>
      8 using namespace std;
      9 #define MAXN 20000
     10 #define MAXM 444444
     11 
     12 struct Edge{
     13     int v,next;
     14 }edge[MAXM];
     15 
     16 int n,m,NE;
     17 int head[MAXN];
     18 
     19 void Insert(int u,int v)
     20 {
     21     edge[NE].v=v;
     22     edge[NE].next=head[u];
     23     head[u]=NE++;
     24 }
     25 
     26 int cnt,bcc_count;
     27 int low[MAXN],dfn[MAXN],color[MAXN];
     28 bool mark[MAXN];
     29 stack<int>S;
     30 
     31 void Tarjan(int u)
     32 {
     33     low[u]=dfn[u]=++cnt;
     34     mark[u]=true;
     35     S.push(u);
     36     for(int i=head[u];i!=-1;i=edge[i].next){
     37         int v=edge[i].v;
     38         if(dfn[v]==0){
     39             Tarjan(v);
     40             low[u]=min(low[u],low[v]);
     41         }else if(mark[v]){
     42             low[u]=min(low[u],dfn[v]);
     43         }
     44     }
     45     if(low[u]==dfn[u]){
     46         int v;
     47         bcc_count++;
     48         do{
     49             v=S.top();
     50             S.pop();
     51             mark[v]=false;
     52             color[v]=bcc_count;
     53         }while(u!=v);
     54     }
     55 }
     56 
     57 int opp[MAXN];
     58 bool Judge()
     59 {
     60     for(int i=1;i<=n;i++){
     61         if(color[i]==color[i+n])return false;
     62         //opp[x]保存的是和编号为x的连通分量矛盾的连通分量的编号
     63         opp[color[i]]=color[i+n];
     64         opp[color[i+n]]=color[i];
     65     }
     66     return true;
     67 }
     68 
     69 vector<vector<int> >g;
     70 vector<int>ans;
     71 int degree[MAXN];
     72 int vis[MAXN];
     73 
     74 void TopSort()
     75 {
     76     queue<int>que;
     77     for(int i=1;i<=bcc_count;i++){
     78         if(degree[i]==0)que.push(i);
     79     }
     80     while(!que.empty()){
     81         int u=que.front();
     82         que.pop();
     83         if(vis[u]==0){
     84             //染色
     85             vis[u]=1;
     86             vis[opp[u]]=-1;
     87         }
     88         for(int i=0;i<g[u].size();i++){
     89             degree[g[u][i]]--;
     90             if(degree[g[u][i]]==0)que.push(g[u][i]);
     91         }
     92     }
     93 }
     94 
     95 
     96 int main()
     97 {
     98     int _case,t=1,a,b,u,v;
     99     scanf("%d",&_case);
    100     while(_case--){
    101         scanf("%d %d",&m,&n);
    102         NE=0;
    103         memset(head,-1,sizeof(head));
    104         while(m--){
    105             scanf("%d%d",&a,&b);
    106             u=abs(a),v=abs(b);
    107             if(a>0&&b>0)Insert(u+n,v),Insert(v+n,u);
    108             else if(a>0&&b<0)Insert(u+n,v+n),Insert(v,u);
    109             else if(a<0&&b>0)Insert(u,v),Insert(v+n,u+n);
    110             else Insert(u,v+n),Insert(v,u+n);
    111         }
    112         cnt=bcc_count=0;
    113         memset(mark,false,sizeof(mark));
    114         memset(dfn,0,sizeof(dfn));
    115         memset(color,0,sizeof(color));
    116         for(int i=1;i<=2*n;i++)if(dfn[i]==0)Tarjan(i);
    117         printf("Case %d: ",t++);
    118         if(!Judge()){
    119             puts("No");
    120             continue;
    121         }
    122         puts("Yes");
    123         //反向建图
    124         memset(degree,0,sizeof(degree));
    125         g.clear();
    126         g.resize(2*n+2);
    127         for(int u=1;u<=2*n;u++){
    128             for(int i=head[u];i!=-1;i=edge[i].next){
    129                 int v=edge[i].v;
    130                 if(color[u]!=color[v]){
    131                     g[color[v]].push_back(color[u]);
    132                     degree[color[u]]++;
    133                 }
    134             }
    135         }
    136         memset(vis,0,sizeof(vis));
    137         TopSort();
    138         ans.clear();
    139         for(int i=1;i<=n;i++){
    140             if(vis[color[i]]==1)ans.push_back(i);
    141         }
    142         printf("%d",(int)ans.size());
    143         sort(ans.begin(),ans.end());
    144         for(int i=0;i<(int)ans.size();i++){
    145             printf(" %d",ans[i]);
    146         }
    147         puts("");
    148      }
    149     return 0;
    150 }
    View Code
  • 相关阅读:
    LightOJ--1094-- Farthest Nodes in a Tree(树的直径裸题)
    poj--1383--Labyrinth(树的直径)
    C字符数组和C++字符串
    Miracl库学习
    GBDT学习
    Java编程规范
    关于JS中的数组[]的方法
    焦点离开事件
    Firebug 安装方法
    JAVASE 中的String的字符串
  • 原文地址:https://www.cnblogs.com/wally/p/3335713.html
Copyright © 2020-2023  润新知