博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Contest20180311]朋友
阅读量:7001 次
发布时间:2019-06-27

本文共 2412 字,大约阅读时间需要 8 分钟。

是毒瘤的friends呢~

注意到“产生感情”和后缀自动机的$Right$集合定义很像,所以先对所有串建广义sam,那么一个节点$s$里的所有串都互相产生感情,而从起点走到$s$走最长路所经过的节点里的串都和$s$的串认识(因为是前缀关系)

所以这题其实是求用最少的仅在起点相交的链覆盖广义sam

把每个节点拆成两个点,连一条容量限制为$[1,1]$的边,对于所有原sam中的转移,连一条边$[0,1]$,最后新建一个汇点,把所有非起点的点连一条$[0,1]$到汇点,跑最小流即可

这样做保证每个点都仅被经过一次且路径不相交

关于上下界网络流,可以去看一看,这里不乱写了

p.s.dicnic加了优化真的是可以为所欲为的,不加就直接被kill掉,加了就100msA掉,代码中有注释符号的地方就是优化

#include
#include
#define inf 10000000int min(int a,int b){return a
0){ dis[to[i]]=dis[x]+1; if(to[i]==tt)return 1;// tail++; q[tail]=to[i]; } } } return dis[tt]>0; } int dfs(int x,int flow){ if(x==tt)return flow; int i,f; for(i=cur[x];i;i=nex[i]){// if(cap[i]>0&&dis[to[i]]==dis[x]+1){ f=dfs(to[i],min(flow,cap[i])); if(f){ cap[i]-=f; cap[i^1]+=f; if(cap[i])cur[x]=i;// return f; } } } dis[x]=-1;// return 0; } int dicnic(){ int ans=0,tmp; while(bfs()){ memcpy(cur,h,sizeof(h));// while(tmp=dfs(ss,inf))ans+=tmp; } return ans; } void gao(){ dicnic(); eadd(t,s,inf,0); s=dicnic(); for(int i=2;i<=M;i++){ if(ex[i]&&cap[i]!=0){ s=0; break; } } printf("%d",s); }}namespace str{ struct sam{ int ch[1010],fa,v; }t[10010]; int M=1; int extend(int p,int c){ int q,nq; if(t[p].ch[c]){ q=t[p].ch[c]; if(t[q].v==t[p].v+1) return q; else{ nq=++M; t[nq]=t[q]; t[nq].v=t[p].v+1; t[q].fa=nq; while(p&&t[p].ch[c]==q){ t[p].ch[c]=nq; p=t[p].fa; } return nq; } }else{ int np=++M; t[np].v=t[p].v+1; while(p&&t[p].ch[c]==0){ t[p].ch[c]=np; p=t[p].fa; } if(p==0) t[np].fa=1; else{ q=t[p].ch[c]; if(t[q].v==t[p].v+1) t[np].fa=q; else{ nq=++M; t[nq]=t[q]; t[nq].v=t[p].v+1; t[np].fa=t[q].fa=nq; while(p&&t[p].ch[c]==q){ t[p].ch[c]=nq; p=t[p].fa; } } } return np; } } int x[5010]; void gao(){ int k,m,n,i,j; scanf("%d%d",&k,&m); while(m--){ scanf("%d",&n); i=1; while(n--){ scanf("%d",&j); i=extend(i,j); } } gra::s=1; gra::t=M+1; gra::ss=M<<1|1; gra::tt=(M<<1)+2; for(i=1;i<=k;i++){ if(t[1].ch[i])gra::eadd(1,t[1].ch[i],inf,0); } for(i=2;i<=M;i++){ gra::eadd(gra::ss,i+M,1,1); gra::eadd(i,gra::tt,1,1); for(j=1;j<=k;j++){ if(t[i].ch[j])gra::eadd(i+M,t[i].ch[j],1,0); } gra::eadd(i+M,M+1,1,0); } }}int main(){ str::gao(); gra::gao();}

转载于:https://www.cnblogs.com/jefflyy/p/8550088.html

你可能感兴趣的文章
状态码202_HTTP状态码(HTTP Status Code)
查看>>
sharepoint 2010 网站集定期备份
查看>>
管理SCCM/MDT中的驱动分类
查看>>
java之HashTable
查看>>
Windows Server 2012体验之配置存储池
查看>>
轻松上手移动互联——百度SiteApp建造日志
查看>>
我从跑步中领悟到了什么?
查看>>
你的权限等于你的可见度
查看>>
Gartner:威胁情报的定义
查看>>
redis多实例重启脚本
查看>>
开发人员学Linux(4):使用JMeter对网站和数据库进行压力测试
查看>>
在51系列中data,idata,xdata,pdata的区别
查看>>
【Deeplearning】关注书目
查看>>
【再见RMQ】NYOJ-119-士兵杀敌(三),区间内大小差值
查看>>
loadrunner中Run-time-Setting设置
查看>>
SSL连接建立过程分析(1)
查看>>
port与大全portClose方法
查看>>
美丽的数学家:如果您讨厌数学,这些其实都是人生故事
查看>>
Kettle 中转换(transformation)的执行过程
查看>>
读书笔记-互联网思维阅读10其中一本书《自由》
查看>>