JZOJ 3862. 【JSOI2014】病毒分类

题目

这里写图片描述

解题思路

可以想到,将字符串排序之后,字符串a与字符串b连边表示a和b只能够选一个。然后问题转化为给图上的点染色,边连着的两点颜色不能相同。问最少有多少种颜色。不会。
学习了网络流模型的转化后,可以转化为匹配(最小割模型)。将前缀类型和后缀类型视为一个个点,S向前缀类型连边,后缀类型向T连边,容量为1,对应的前缀类型和后缀类型连的边,容量为正无穷,表示这条边不能割。
另外一种直接的模型就是二分图匹配了。与网络图中的边的意义一样,表示选了某个前缀类型后,就不能够选对应的后缀类型。
其实这两种方法具有相通性。
问方案?随便搞搞。判断一下哪种前缀/后缀类型算进了答案,对应的方案跑一下图就是了。

某位大神的代码

inline int preprocessing(int pre[]) {
  std::sort(id + 1, id + n + 1, cmp);
  pre[id[1]] = 1;
  for (int i = 2; i <= n; ++i)
    pre[id[i]] = pre[id[i - 1]] + (strncmp(s[id[i - 1]], s[id[i]], k) != 0);
  return pre[id[n]];
}

for (int i = 1; i <= n; ++i) std::reverse(s[i], s[i] + strlen(s[i]));

这样能够大大缩短代码长度。(给字符串排序)

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#define N 3000010
#define M 5010
#define P(a) putchar(a)
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
struct note{
    int to,next;
};note edge[M],edge1[M];
int tot,head[M*2],tot1,head1[M*2];
int i,j,K,k,ans;
int n,m,x,gx,gy,cnt,c1;
char ch,s[N];
int col[M],o[M];
int hl[M],hr[M];
int oL[M],oR[M];
int L[M],R[M],len[M],L1[M],R1[M];
int fl[M],fr[M],match[M*2];
int bz[M*2];
bool vis[M*2];
queue<int>Q;
vector<int>grp[M*2];
int read(){
    int fh=1,res=0;char ch;
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')fh=-1,ch=getchar();
    while(ch>='0'&&ch<='9')res=res*10+ch-'0',ch=getchar();
    return fh*res;
}
void write(int x){if(x>9)write(x/10);P(x%10+'0');}
void mi(int &x,int y){x=x<y?x:y;}
void ma(int &x,int y){x=x>y?x:y;}
int getl(int x){return fl[x]==x?x:fl[x]=getl(fl[x]);}
int getr(int x){return fr[x]==x?x:fr[x]=getr(fr[x]);}
int cl(int l1,int l2){
    l1=L1[l1];
    int i,l=len[l1]<len[l2]?len[l1]:len[l2];
    fo(i,1,l)
        if(s[L[l1]+i-1]>s[L[l2]+i-1])return 2;else
        if(s[L[l1]+i-1]<s[L[l2]+i-1])return 1;
    if(len[l1]>len[l2])return 2;
    if(len[l1]<len[l2])return 1;
    return 0;
}
int cr(int l1,int l2){
    l1=R1[l1];
    int i,l=len[l1]<len[l2]?len[l1]:len[l2];
    fo(i,1,l)
        if(s[R[l1]-i+1]>s[R[l2]-i+1])return 2;else
        if(s[R[l1]-i+1]<s[R[l2]-i+1])return 1;
    if(len[l1]>len[l2])return 2;
    if(len[l1]<len[l2])return 1;
    return 0;
}
void ql(int l,int r){
    int i=l,j=r,mid=L1[(l+r)/2];
    while(i<j){
        while(cl(i,mid)==1)i++;
        while(cl(j,mid)==2)j--;
        if(i<=j)swap(L1[i],L1[j]),i++,j--;
    }
    if(l<j)ql(l,j);
    if(i<r)ql(i,r);
}
void qr(int l,int r){
    int i=l,j=r,mid=R1[(l+r)/2];
    while(i<j){
        while(cr(i,mid)==1)i++;
        while(cr(j,mid)==2)j--;
        if(i<=j)swap(R1[i],R1[j]),i++,j--;
    }
    if(l<j)qr(l,j);
    if(i<r)qr(i,r);
}
void get_hl(){
    int i,j,l,a1,b1;
    fo(i,1,n-1){
        a1=L1[i];b1=L1[i+1];
        l=len[a1]<len[b1]?len[a1]:len[b1];
        fo(j,1,l){
            if(s[L[a1]+j-1]!=s[L[b1]+j-1])
                break;
        }
        hl[i]=j-1;
    }
}
void get_hr(){
    int i,j,l,a1,b1;
    fo(i,1,n-1){
        a1=R1[i];b1=R1[i+1];
        l=len[a1]<len[b1]?len[a1]:len[b1];
        fo(j,1,l){
            if(s[R[a1]-j+1]!=s[R[b1]-j+1])
                break;
        }
        hr[i]=j-1;
    }
}
void conl(int x,int y){gx=getl(x);gy=getl(y);if(gx!=gy)fl[gy]=gx;}
void conr(int x,int y){gx=getr(x);gy=getr(y);if(gx!=gy)fr[gy]=gx;}
void lb(int x,int y){edge[++tot].to=y;edge[tot].next=head[x];head[x]=tot;}
void lb1(int x,int y){edge1[++tot1].to=y;edge1[tot1].next=head1[x];head1[x]=tot1;}
bool find(int x){
    int i;
    for(i=head[x];i;i=edge[i].next)
        if(bz[edge[i].to]!=bz[0]){
            bz[edge[i].to]=bz[0];
            if(!match[edge[i].to]||find(match[edge[i].to])){
                match[edge[i].to]=x;
                return 1;
            }
        }
    return 0;
}
void work(){
    int i,hd=0,tl=1,x;
    fo(i,c1+1,c1+cnt)if(!match[i])Q.push(i);else col[i]=1;
    while(!Q.empty()){
        x=Q.front();Q.pop();
        vis[x]=1;
        col[x]=0;
        for(i=head1[x];i;i=edge1[i].next)
            if(!vis[edge1[i].to]){
                vis[edge1[i].to]=1;
                col[edge1[i].to]=1;
                if(match[edge1[i].to])Q.push(match[edge1[i].to]);
            }
    }
}
int main(){
    n=read();K=read();
    fo(i,1,n){
        L[i]=R[i]=R[i-1]+1;R[i]--;
        ch=getchar();
        while(ch<'A'||ch>'Z')ch=getchar();
        while(ch>='A'&&ch<='Z')s[++R[i]]=ch,ch=getchar();
        len[i]=R[i]-L[i]+1;
        L1[i]=R1[i]=i; 
    }
    ql(1,n);
    qr(1,n);
    fo(i,1,n)oL[L1[i]]=oR[R1[i]]=i;
    get_hl();
    get_hr();
    fo(i,1,n)fl[i]=fr[i]=i;
    fo(i,1,n-1)if(hl[i]>=K)conl(i,i+1);
    fo(i,1,n-1)if(hr[i]>=K)conr(i,i+1);
    memcpy(o,fl,sizeof(o));
    sort(o+1,o+n+1);cnt=unique(o+1,o+n+1)-o-1;
    fo(i,1,n)fl[i]=lower_bound(o+1,o+cnt+1,fl[i])-o;
    c1=cnt;
    memcpy(o,fr,sizeof(o));
    sort(o+1,o+n+1);cnt=unique(o+1,o+n+1)-o-1;
    fo(i,1,n)fr[i]=lower_bound(o+1,o+cnt+1,fr[i])-o;
    fo(i,1,n)fr[i]+=c1;
    fd(i,n,1){
        lb(fl[oL[i]],fr[oR[i]]),lb1(fr[oR[i]],fl[oL[i]]);
    }
    fo(i,1,c1)if(!match[i]){
        bz[0]++;bz[i]=bz[0];
        ans+=find(i);
    }
    write(ans),P('\n');
    fo(i,1,c1+cnt)match[match[i]]=i;
    work();
    fo(i,1,n){
        gx=col[fl[oL[i]]]?fl[oL[i]]:fr[oR[i]];
        grp[gx].push_back(i);
    }
    fo(i,1,M-20)if(grp[i].size()){
        write(grp[i].size());P(' ');
        fo(j,0,grp[i].size()-1)write(grp[i][j]),P(' ');
        P('\n');
    }
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值