2 -- sat 整理

HDU 3062

简单的判断,裸的2SAT

#include <cstdio>
#include <cstring>
const int N = 2100;
const int M = 1100 * 1000 * 2;
struct Node
{
    int adj,next;
} node[M];
struct TT
{
    int DFN,LOW,belongs;
} num[N];
int first[N],n,e;
bool instack[N];
int stack[N],b_cnt,idx,top;
void init()
{
    e=0;
    for(int i=0; i<=2*n; i++)
    {
        first[i]=-1;
        num[i].DFN=num[i].LOW=0;
        num[i].belongs=0;
        instack[i]=false;
    }
}
void insertEdge(int u,int v)
{
    node[e].adj=v;
    node[e].next=first[u];
    first[u]=e++;;
}
void Tarjan(int u)
{
    int v;
    num[u].DFN=num[u].LOW=(++idx);
    instack[u]=true;
    stack[++top]=u;
    for(int p=first[u]; p!=-1; p=node[p].next)
    {
        v=node[p].adj;
        if(!num[v].DFN)
        {
            Tarjan(v);
            if(num[v].LOW<num[u].LOW)
                num[u].LOW=num[v].LOW;
        }
        else if(instack[v]&&num[v].DFN<num[u].LOW)
            num[u].LOW=num[v].DFN;
    }
    if(num[u].DFN==num[u].LOW)
    {
        b_cnt++;
        do
        {
            v=stack[top--];
            instack[v]=false;
            num[v].belongs=b_cnt;
        }
        while(u!=v);
    }
}
bool Tarjan_SCC()
{
    b_cnt=top=idx=0;
    for(int i=0; i<2*n; i++)
        if(!num[i].DFN) Tarjan(i);
    for(int i=0; i<2*n; i+=2)
        if(num[i].belongs==num[i^1].belongs)
            return false;
    return true;
}
int main()
{
    int m;
    while (scanf("%d%d",&n,&m)==2)
    {
        init();
        int a,b,c,d;
        for (int i=0; i<m; ++i)
        {
            scanf("%d%d%d%d",&a,&b,&c,&d);
            if(c)  a= 2 * a + 1;
            else a = 2 * a;
            if(d) b= 2 * b + 1;
            else b = 2 * b;
            insertEdge(a, b^1);
            insertEdge(b, a^1);
        }
        if (!Tarjan_SCC())
        {
            printf("NO\n");
        }
        else
            printf("YES\n");
    }
    return 0;
}



hdu  1824  题目描述不是特别清楚吧

#include <cstdio>
#include <cstring>
const int N = 1010 * 6;
const int M = 100000;
struct Node
{
    int adj,next;
} node[M];
struct TT
{
    int DFN,LOW,belongs;
} num[N];
int first[N],n,e;
bool instack[N];
int stack[N],b_cnt,idx,top;
void init()
{
    e=0;
    for(int i=0; i<=6*n; i++)
    {
        first[i]=-1;
        num[i].DFN=num[i].LOW=0;
        num[i].belongs=0;
        instack[i]=false;
    }
}
void insertEdge(int u,int v)
{
    node[e].adj=v;
    node[e].next=first[u];
    first[u]=e++;;
}
void Tarjan(int u)
{
    int v;
    num[u].DFN=num[u].LOW=(++idx);
    instack[u]=true;
    stack[++top]=u;
    for(int p=first[u]; p!=-1; p=node[p].next)
    {
        v=node[p].adj;
        if(!num[v].DFN)
        {
            Tarjan(v);
            if(num[v].LOW<num[u].LOW)
                num[u].LOW=num[v].LOW;
        }
        else if(instack[v]&&num[v].DFN<num[u].LOW)
            num[u].LOW=num[v].DFN;
    }
    if(num[u].DFN==num[u].LOW)
    {
        b_cnt++;
        do
        {
            v=stack[top--];
            instack[v]=false;
            num[v].belongs=b_cnt;
        }
        while(u!=v);
    }
}
bool Tarjan_SCC()
{
    b_cnt=top=idx=0;
    for(int i=0; i<6*n; i++)
        if(!num[i].DFN) Tarjan(i);
    for(int i=0; i<3*n; i++)
        if(num[i].belongs==num[i+3*n].belongs)
            return false;
    return true;
}
int main()
{
    int m;
    while(scanf("%d%d", &n, &m) != EOF)
    {
        init();
        int te = n * 3;
        int a, b, c;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d%d", &a, &b, &c);
            insertEdge(a, b + te);//a和b,c之间的互斥关系
            insertEdge(a, c + te);
            insertEdge(b, a + te);
            insertEdge(c, a + te);
            insertEdge(a + te, b);
            insertEdge(a + te, c);
            insertEdge(b + te, a);
            insertEdge(c + te, a);

            insertEdge(b, c);
            insertEdge(c, b);
            insertEdge(b + te, c + te);
            insertEdge(c + te, b + te);
            //
        }

        for(int i = 1; i <= m; i++)
        {
            scanf("%d%d", &a, &b);
            insertEdge(a, b + te);
            insertEdge(b, a + te);//注意a+te和b+te是没有影响的
        }

        if(Tarjan_SCC())  printf("yes\n");
        else printf("no\n");

    }
    return 0;
}


hdu 3715  去年成都赛区的一道题目,二分一下就行了

#include <cstdio>
#include <cstring>
const int N = 210 * 3;
const int M = 210 * 210 * 3;
struct Node
{
    int adj,next;
} node[M];
struct TT
{
    int DFN,LOW,belongs;
} num[N];
int first[N],n,e,m;
bool instack[N];
int stack[N],b_cnt,idx,top;
int a[10010], b[10010], c[10010];
void init()
{
    e=0;
    memset(first, -1, sizeof(first));
    memset(instack, 0, sizeof(instack));
    for(int i=0; i<=2*n; i++)
    {
        num[i].DFN=num[i].LOW=0;
        num[i].belongs=0;
    }
}
void insertEdge(int u,int v)
{
    node[e].adj=v;
    node[e].next=first[u];
    first[u]=e++;;
}
void Tarjan(int u)
{
    int v;
    num[u].DFN=num[u].LOW=(++idx);
    instack[u]=true;
    stack[++top]=u;
    for(int p=first[u]; p!=-1; p=node[p].next)
    {
        v=node[p].adj;
        if(!num[v].DFN)
        {
            Tarjan(v);
            if(num[v].LOW<num[u].LOW)
                num[u].LOW=num[v].LOW;
        }
        else if(instack[v]&&num[v].DFN<num[u].LOW)
            num[u].LOW=num[v].DFN;
    }
    if(num[u].DFN==num[u].LOW)
    {
        b_cnt++;
        do
        {
            v=stack[top--];
            instack[v]=false;
            num[v].belongs=b_cnt;
        }
        while(u!=v);
    }
}
bool Tarjan_SCC()
{
    b_cnt=top=idx=0;
    for(int i=0; i<2*n; i++)
        if(!num[i].DFN) Tarjan(i);
    for(int i=0; i<2*n; i+=2)
        if(num[i].belongs==num[i^1].belongs)
            return false;
    return true;
}
bool  check(int dep)
{
    init();
    for(int i = 0; i < dep; i++)
    {
        int x = a[i];// 0..2*x   1..2*x+1
        int y = b[i];
        if(c[i] == 2)
        {
            //x[a] + y[b] != 2
            insertEdge(x * 2 + 1, y * 2);
            insertEdge(y * 2 + 1, x * 2);
        }
        else if(c[i] == 1)
        {
            insertEdge(x * 2 + 1, y * 2 + 1);
            insertEdge(y * 2 + 1, x * 2 + 1);
            insertEdge(x * 2, y * 2);
            insertEdge(y * 2, x * 2);
        }
        else
        {
            insertEdge(x * 2, y * 2 + 1);
            insertEdge(y * 2, x * 2 + 1);
        }
    }
    if(Tarjan_SCC())  return true;
    else return false;
}
void solve(int m)
{
    int l = 0, r = m;
    int ans = l;
    while(l <= r)
    {
        int mid = (l + r) / 2;
        //printf("mid = %d\n", mid);
        if(check(mid))
        {
            if(mid > ans)  ans = mid;
            l = mid + 1;
        }
        else
        r = mid - 1;
    }
    printf("%d\n", ans);
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &n, &m);
        for(int i = 0; i < m; i++)
        {
            scanf("%d%d%d", &a[i], &b[i], &c[i]);
        }
        solve(m);
    }
    return 0;
}



HDU 3622  去年天津赛区的一道预选赛的题目

#include <cstdio>
#include <cstring>
#include <cmath>
const double eps=1e-10;//注意这个要开大
struct T_T
{
    int x,y;
} q[505];
struct Node
{
    int adj,next;
} node[505*505];
struct TT
{
    int DFN,LOW,belongs;
} num[505];
int first[550],n,e;
double map[505][505];
double min,max;
bool instack[550];
int stack[550],b_cnt,idx,top;
double len(int i,int j)
{
    return sqrt(1.0*(q[i].x-q[j].x)*(q[i].x-q[j].x)+1.0*(q[i].y-q[j].y)*(q[i].y-q[j].y));
}
void init()
{
    e=0;
    for(int i=1; i<=2*n; i++)
    {
        first[i]=-1;
        num[i].DFN=num[i].LOW=0;
        num[i].belongs=0;
        instack[i]=false;
    }
}
void insertEdge(int u,int v)
{
    node[e].adj=v;
    node[e].next=first[u];
    first[u]=e++;;
}
void Tarjan(int u)
{
    int v;
    num[u].DFN=num[u].LOW=(++idx);
    instack[u]=true;
    stack[++top]=u;
    for(int p=first[u]; p!=-1; p=node[p].next)
    {
        v=node[p].adj;
        if(!num[v].DFN)
        {
            Tarjan(v);
            if(num[v].LOW<num[u].LOW)
                num[u].LOW=num[v].LOW;
        }
        else if(instack[v]&&num[v].DFN<num[u].LOW)
            num[u].LOW=num[v].DFN;
    }
    if(num[u].DFN==num[u].LOW)
    {
        b_cnt++;
        do
        {
            v=stack[top--];
            instack[v]=false;
            num[v].belongs=b_cnt;
        }
        while(u!=v);
    }
}
bool Tarjan_SCC()
{
    b_cnt=top=idx=0;
    for(int i=1; i<=2*n; i++)
        if(!num[i].DFN) Tarjan(i);
    for(int i=1; i<=n; i++)
        if(num[i].belongs==num[i+n].belongs)
            return false;
    return true;
}
bool check(double d)
{
    init();
    for(int i=1; i<=n; i++)
        for(int j=i+1; j<=n; j++)
        {
            if(map[i][j]<d) insertEdge(i,j+n),insertEdge(j,i+n);
            if(map[i][j+n]<d) insertEdge(i,j),insertEdge(j+n,i+n);
            if(map[i+n][j]<d) insertEdge(i+n,j+n),insertEdge(j,i);
            if(map[i+n][j+n]<d) insertEdge(i+n,j),insertEdge(j+n,i);
        }
    return Tarjan_SCC();
}
double solve()
{
    double ans=min;
    while(fabs(max-min)>=eps)
    {
        double mid=(min+max)/2;
        if(check(mid))
        {
            if(ans<mid) ans=mid;
            min=mid;
        }
        else max=mid;
    }
    return ans;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1; i<=n; i++)
        {
            scanf("%d%d",&q[i].x,&q[i].y);
            scanf("%d%d",&q[i+n].x,&q[i+n].y);
        }
        min=1000000.00,max=-1.0;
        for(int i=1; i<=2*n; i++)
            for(int j=1; j<=2*n; j++)
            {
                double l=len(i,j);
                if(l>max) max=l;
                if(l<min) min=l;
                map[i][j]=l;
            }
        printf("%0.2lf\n",solve()/2);
    }
    return 0;
}



评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值