zoukankan      html  css  js  c++  java
  • [JSOI2014]学生选课(二分+2-SAT)

    乍看上去是一道难题,实际上是一道裸题。

    看到这种直接求最大摸不着头脑的题,首先就想到二分。由于每个人只能选择两种课,因此就是个简单的2-SAT问题,将大于二分值的关系视为限制条件即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1010;
    struct edge{int v,nxt;}e[N*N* 4];
    int n,tot,num,col,top,tp[N],a[N][2],f[N][N],hd[N*3],dfn[N*3],low[N*3],bel[N*3],st[N*3];
    void adde(int u,int v){e[++tot]=(edge){v,hd[u]},hd[u]=tot;}
    void tarjan(int u)
    {
        dfn[u]=low[u]=++num,st[++top]=u;
        for(int i=hd[u];i;i=e[i].nxt)
        if(!dfn[e[i].v])tarjan(e[i].v),low[u]=min(low[u],low[e[i].v]);
        else if(!bel[e[i].v])low[u]=min(low[u],dfn[e[i].v]);
        if(low[u]==dfn[u])
        {
            col++;
            do bel[st[top]]=col;while(st[top--]!=u);
        }
    }
    int id(int x,int y){return y*(n+1)+x;}
    bool check(int mid)
    {
        tot=num=col=top=0;
        memset(hd,0,sizeof hd);
        memset(dfn,0,sizeof dfn);
        memset(low,0,sizeof low);
        memset(bel,0,sizeof bel);
        for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        if(f[i][j]>mid)
        for(int x=0;x<2;x++)for(int y=0;y<2;y++)if(a[i][x]==a[j][y])
        adde(id(i,a[i][x]),id(j,a[j][y^1])),adde(id(j,a[j][y]),id(i,a[i][x^1]));
        for(int i=1;i<=n;i++)
        for(int k=0;k<3;k++)
        if(tp[i]!=k&&!dfn[id(i,k)])tarjan(id(i,k));
        for(int i=1;i<=n;i++)if(bel[id(i,a[i][0])]==bel[id(i,a[i][1])])return 0;
        return 1;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&tp[i]);
            if(tp[i]==0)a[i][0]=1,a[i][1]=2;
            if(tp[i]==1)a[i][0]=0,a[i][1]=2;
            if(tp[i]==2)a[i][0]=0,a[i][1]=1;
            for(int j=1,x;j<n;j++)scanf("%d",&x),f[i][x]=j;
        }
        for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        f[i][j]=max(f[i][j],f[j][i]);
        int l=1,r=n-1,mid;
        while(l<r)
        {
            mid=l+r>>1;
            if(check(mid))r=mid;else l=mid+1;
        }
        printf("%d",l);
    }
  • 相关阅读:
    sqlserver 行转列 语文,数学,物理,化学
    除去字符串中不相临的重复的字符 aabcad 得 aabcd
    Mvc项目实例 MvcMusicStore 五
    c# 计算两日期的工作时间间隔(排除非工作日)及计算下一个工作时间点.
    html-----016---HTTP 状态消息
    html-----015---HTML ASCII 参考手册
    html-----014---统一资源定位器
    html-----013----实体字符/HTML URL 编码
    html-----012---颜色的改变
    html-----011--子窗体iframe
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/14364317.html
Copyright © 2011-2022 走看看