【2-SAT】Codeforces 876E National Property

题面在这里

其实就是2-SAT……

对于每个字母,考虑是否改掉

那么只需要相邻两个满足字典序,所有的单词就都满足字典序了

然后应该很好处理吧……

nm打反狂WA 3发……

示例程序:

#include<cstdio>
#include<vector>
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int red(){
    int res=0,f=1;char ch=nc();
    while (ch<'0'||'9'<ch) {if (ch=='-') f=-f;ch=nc();}
    while ('0'<=ch&&ch<='9') res=res*10+ch-48,ch=nc();
    return res*f;
}

const int maxn=200005,maxe=400005;
int N,n,m,l[maxn];
vector<int> s[maxn];
int son[maxe],lnk[maxn],nxt[maxe],tot;
inline void add(int x,int y){
    son[++tot]=y;nxt[tot]=lnk[x];lnk[x]=tot;
}
int dfn[maxn],low[maxn],stk[maxn],to[maxn],Tim,scc[maxn];
bool instk[maxn];
void tarjan(int x){
    stk[++stk[0]]=x;instk[x]=1;
    dfn[x]=low[x]=++Tim;
    for (int j=lnk[x];j;j=nxt[j])
     if (!dfn[son[j]]) tarjan(son[j]),low[x]=min(low[x],low[son[j]]);else
     if (instk[son[j]]) low[x]=min(low[x],dfn[son[j]]);
    if (low[x]==dfn[x]){
        scc[0]++;
        while (stk[stk[0]+1]!=x)
         instk[stk[stk[0]]]=0,scc[stk[stk[0]--]]=scc[0];
    }
}
int main(){
    n=red(),m=red();
    for (int i=1;i<=n;i++){
        l[i]=red();s[i].push_back(0);
        for (int j=1;j<=l[i];j++) s[i].push_back(red());
    }
    for (int i=1;i<n;i++){
        bool fir=1;
        for (int j=1;j<=l[i]&&j<=l[i+1];j++)
         if (fir&&s[i][j]!=s[i+1][j]){
            fir=0;int a=s[i][j],b=s[i+1][j];
            if (a<b)
             add(a<<1,b<<1),add(b<<1|1,a<<1|1);
            else
             add(a<<1,a<<1|1),add(b<<1|1,b<<1);
         }
        if (fir&&l[i+1]<l[i]) return printf("No"),0; 
    }
    N=m<<1|1;
    for (int i=2;i<=N;i++)
     if (!dfn[i]) tarjan(i);
    int tot=0;
    for (int i=1;i<=m;i++)
     if (scc[i<<1]==scc[i<<1|1]) return printf("No"),0;
      else if (scc[i<<1|1]<scc[i<<1]) tot++;
    printf("Yes\n%d\n",tot);
    for (int i=1;i<=m;i++)
     if (scc[i<<1|1]<scc[i<<1]) printf("%d ",i);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值