zoukankan      html  css  js  c++  java
  • hud 3062 Party

    题意:中文的,不解释了

    思路:2-sat基本题,练习的第一道题目,网上找了个模板

    话说这个vector< vector<int> >还真是弄了好久的,所以先

    写了一个一维的弄了好久好久……2-sat终于有点思路了,各种错啊……

    这个是一维的:

    #include<iostream>
    #include<string>
    #include<vector>
    #include<stack>
    #include <cstdio>
    #include<algorithm>
    #include <cstring>
    using namespace std;

    const int N=2005;

    vector<int>map1[N];
    vector<int>map2[N];

    bool used[N],flag[N][N];

    int order[N],id[N];
    int m,n,cnt,color;

    void Init()
    {
    for(int i=0;i<2*n;i++)
    {
    map1[i].clear();
    map2[i].clear();
    }
    }

    void addedge(int from,int to)
    {
    map1[from].push_back(to);
    map2[to].push_back(from);
    }

    void build_map1()
    {
    int i,x,y,u,v,uu,vv;
    for(i=0;i<m;i++)
    {
    scanf("%d%d%d%d",&x,&y,&u,&v);
    u=2*x+u;
    uu=(u%2)?u-1:u+1;
    v=2*y+v;
    vv=(v%2)?v-1:v+1;
    addedge(u,vv);
    addedge(v,uu);
    }
    }

    void dfs1(int u) //把所有的点正向压缩
    {
    used[u]=true;
    for(int i=0;i<map1[u].size();i++)
    if(!used[map1[u][i]])
    dfs1(map1[u][i]);
    order[cnt++]=u;
    }

    void dfs2(int u)
    {
    used[u]=true;
    id[u]=color;
    for(int i=0;i<map2[u].size();i++)
    if(!used[map2[u][i]])
    dfs2(map2[u][i]);
    }

    bool sat()
    {
    int i;
    memset(used,0,sizeof(used));
    color=cnt=0;
    for(i=0;i<2*n;i++)
    if(!used[i])
    dfs1(i);
    memset(used,0,sizeof(used));
    for(i=cnt-1;i>=0;i--)
    if(!used[order[i]])
    {
    color++;
    dfs2(order[i]);
    }
    for(i=0;i<2*n;i+=2)
    if(id[i]==id[i+1])
    return 0;
    return 1;
    }


    int main()
    {
    while(scanf("%d%d",&n,&m)!=EOF)
    {
    if(n==0&&m==0)
    break;
    Init();
    build_map1();
    if(!sat())
    printf("NO\n");
    else
    printf("YES\n");
    }
    return 0;
    }
    /*
    这个是二维的:

    */

    #include <iostream>
    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    using namespace std;
    const int Maxn=2010;//2*N
    bool visit[Maxn];//标记
    vector< vector<int> > adj;//正向图
    vector< vector<int> > radj;//逆向图
    int n,m,cnt,id[Maxn],order[Maxn];
    //n表示点对数,m表示矛盾,id[]表示缩点后点对应的新点的标号
    //order[]是强连通时使用korasaju记录搜索的次序
    void Init()
    {
    for(int i=0; i<2*n; i++)
    {
    adj[i].resize(Maxn);
    radj[i].resize(Maxn);
    }
    }
    void init()
    {
    for(int i=0; i<2*n; i++)
    {
    adj[i].clear();
    radj[i].clear();
    }
    }

    void AddEdge(int from, int to)
    {
    adj[from].push_back(to);
    radj[to].push_back(from);
    }

    void BuildGraph()
    {
    int u, v, x, y;
    for(int i=0; i<m; i++)
    {
    scanf("%d%d%d%d", &x, &y, &u, &v);
    u=2*x+u;
    int uu=(u%2)?u-1:u+1;
    v=2*y+v;
    int vv=(v%2)?v-1:v+1;
    AddEdge(u, vv);
    AddEdge(v, uu);
    }
    }
    void dfs(int u)//求强联通时的正向搜索进行标号
    {
    visit[u]=true;
    int i,len=adj[u].size();
    for(i=0; i<len; i++)
    if(!visit[adj[u][i]])
    dfs(adj[u][i]);
    order[cnt++]=u;//标号从0开始,上面的点后标号,表示从正向的边存在
    }

    void rdfs(int u)//求强联通的逆向搜索
    {
    id[u]=cnt;//进行缩点标记
    visit[u]=true;
    int i,len=radj[u].size();
    for(i=0; i<len; i++)
    if(!visit[radj[u][i]])
    rdfs(radj[u][i]);
    }

    void korasaju()
    {
    int i;
    memset(visit,false,sizeof(visit));
    for(cnt=0,i=0; i<2*n; i++) //正向搜一次
    if(!visit[i])
    dfs(i);
    memset(id,0,sizeof(id));
    memset(visit,false,sizeof(visit));
    for(cnt=0,i=2*n-1; i>=0; i--) //从正向标记大的逆向搜一次.表示逆向的边也存在
    {
    if(!visit[order[i]])
    {
    cnt++;
    rdfs(order[i]);//缩点后点的标号从1开始
    }
    }
    }

    bool solve()//判断同样的缩点中是否有矛盾的点
    {
    for(int i=0; i<2*n; i+=2)
    if(id[i]==id[i+1])
    return false;
    return true;
    }

    int main()
    {
    adj.resize(Maxn);
    radj.resize(Maxn);
    Init();
    while(scanf("%d%d", &n, &m)!=EOF)
    {
    init();
    BuildGraph();
    korasaju();
    if(!solve()) puts("NO");
    else puts("YES");
    }
    return 0;
    }
    作者:FreeAquar
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    java字符串实现正序和倒序输出
    暑假前挑战赛1—— A,B题解
    深搜
    poj 1200 Crazy Search
    poj 1840 Eqs (hash)
    Choose the best route
    一个人的旅行
    畅通工程续
    最短路基础算法
    完全背包问题
  • 原文地址:https://www.cnblogs.com/FreeAquar/p/2104207.html
Copyright © 2011-2022 走看看