http://poj.org/problem?id=2723

2-sat  二分

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#define LL long long

using namespace std;

const int N=5000;
int head1[N],I1;
struct ss
{
    int j,next;
}side1[N*50];
struct key
{
    int i,j;
}dif[N],eith[N];
int low[N],dfn[N],f[N],deep;
bool in[N],visited[N];
stack<int>st;
void build1(int x,int y)
{
    side1[I1].j=y;
    side1[I1].next=head1[x];
    head1[x]=I1++;
}
void Tarjan(int x)
{
    visited[x]=true;
    in[x]=true;
    st.push(x);
    low[x]=dfn[x]=deep++;
    for(int t=head1[x];t!=-1;t=side1[t].next)
    {
        int k=side1[t].j;
        if(visited[k]==false)
        {
            Tarjan(k);
            low[x]=min(low[x],low[k]);
        }else if(in[k]==true)
        {
            low[x]=min(low[x],dfn[k]);
        }
    }
    if(low[x]==dfn[x])
    {
        int k;
        do
        {
            k=st.top();
            st.pop();
            in[k]=false;
            f[k]=x;
        }while(k!=x);
    }
}
bool solve(int m,int n)
{
    memset(head1,-1,sizeof(head1));
    I1=0;
    for(int l=1;l<=n;++l)
    {
        build1(dif[l].i,dif[l].j+2*n);
        build1(dif[l].j,dif[l].i+2*n);
    }
    for(int l=1;l<=m;++l)
    {
        build1(eith[l].i+2*n,eith[l].j);
        build1(eith[l].j+2*n,eith[l].i);
    }
    memset(visited,false,sizeof(visited));
    memset(in,false,sizeof(in));
    memset(f,-1,sizeof(f));
    while(!st.empty())
    st.pop();
    deep=0;
    int l;
    for(l=0;l<2*n;++l)
    {
        if(!visited[l])
        Tarjan(l);
        if(f[l]!=-1&&f[l]==f[l+2*n])
        break;
    }
    if(l<2*n)
    return false;
    else
    return true;

}
int main()
{
    //freopen("data.txt","r",stdin);
    int n,m;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)
        break;
        for(int i=1;i<=n;++i)
        scanf("%d %d",&dif[i].i,&dif[i].j);
        for(int i=1;i<=m;++i)
        scanf("%d %d",&eith[i].i,&eith[i].j);
        int l=1,r=m;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(solve(mid,n))
            l=mid+1;
            else
            r=mid-1;
        }
        printf("%d\n",r);

    }
    return 0;
}

  

posted on 2012-08-17 09:45  夜->  阅读(146)  评论(0编辑  收藏  举报