BZOJ4912 : [Sdoi2017]天才黑客

建立新图,原图中每条边在新图中是点,点权为$w_i$,边权为两个字符串的LCP。

对字典树进行DFS,将每个点周围一圈边对应的字符串按DFS序从小到大排序。

根据后缀数组利用height数组求LCP的原理,类似地可以得到:

令$h_i=LCP(str_i,str_{i+1})$,则$LCP(str_l,str_r)=\min(h_{l..r-1})$。

枚举每个$h_i$作为分界线,那么新图中两侧的点均可以通过不超过$h_i$的代价互相访问。

建立一排前缀虚点和后缀虚点然后对应前后缀之间连边即可。

如此建图的点数和边数均为$O(m)$,时间复杂度$O(m\log m)$。

#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
typedef pair<int,int>P;
const int N=50010,inf=~0U>>1;
int Case,n,m,K,i,j,x,y,z,g[N],nxt[N],size[N],f[N],d[N],son[N],loc[N],top[N],dfn;
int gi[N],go[N],V[N<<1],NXT[N<<1],ED;
int cnt,pi[N<<1],po[N<<1],si[N<<1],so[N<<1],cq,q[N<<1];
inline void read(int&a){char c;while(!(((c=getchar())>=‘0‘)&&(c<=‘9‘)));a=c-‘0‘;while(((c=getchar())>=‘0‘)&&(c<=‘9‘))(a*=10)+=c-‘0‘;}
struct E{int a,b,c,d;}e[N];
namespace G{
const int N=450010,M=800010;
int g[N],v[M],w[M],nxt[M],ed,val[N],d[N];priority_queue<P,vector<P>,greater<P> >q;
inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;}
inline void ext(int x,int y){
  y+=val[x];
  if(y<d[x])q.push(P(d[x]=y,x));
}
void solve(){
  for(i=1;i<=cnt;i++)d[i]=inf;
  for(i=1;i<=m;i++)if(e[i].a==1)ext(i,0);
  while(!q.empty()){
    P t=q.top();q.pop();
    if(d[t.second]>t.first)continue;
    for(i=g[t.second];i;i=nxt[i])ext(v[i],t.first+w[i]);
  }
}
}
inline bool cmp(int x,int y){return loc[e[abs(x)].d]<loc[e[abs(y)].d];}
inline void add(int x,int y){nxt[y]=g[x];g[x]=y;}
inline void ADD(int&x,int y){V[++ED]=y;NXT[ED]=x;x=ED;}
void dfs(int x){
  size[x]=1;
  for(int i=g[x];i;i=nxt[i]){
    f[i]=x,d[i]=d[x]+1;
    dfs(i),size[x]+=size[i];
    if(size[i]>size[son[x]])son[x]=i;
  }
}
void dfs2(int x,int y){
  loc[x]=++dfn;top[x]=y;
  if(son[x])dfs2(son[x],y);
  for(int i=g[x];i;i=nxt[i])if(i!=son[x])dfs2(i,i);
}
inline int lca(int x,int y){
  for(;top[x]!=top[y];x=f[top[x]])if(d[top[x]]<d[top[y]])swap(x,y);
  return min(d[x],d[y]);
}
inline void solve(int x){
  int i;
  if(!gi[x]||!go[x])return;
  cq=0;
  for(i=gi[x];i;i=NXT[i])q[++cq]=V[i];
  for(i=go[x];i;i=NXT[i])q[++cq]=-V[i];
  sort(q+1,q+cq+1,cmp);
  for(i=1;i<=cq;i++){
    pi[i]=++cnt;
    si[i]=++cnt;
    po[i]=++cnt;
    so[i]=++cnt;
    if(i>1){
      G::add(pi[i-1],pi[i],0);
      G::add(po[i-1],po[i],0);
      G::add(si[i],si[i-1],0);
      G::add(so[i],so[i-1],0);
    }
    if(q[i]>0)G::add(q[i],pi[i],0),G::add(q[i],si[i],0);
    else q[i]*=-1,G::add(po[i],q[i],0),G::add(so[i],q[i],0);
  }
  for(i=1;i<cq;i++){
    int t=lca(e[q[i]].d,e[q[i+1]].d);
    G::add(pi[i],po[i+1],t);
    G::add(si[i+1],so[i],t);
  }
}
int main(){
  read(Case);
  while(Case--){
    read(n),read(m),read(K);
    for(i=1;i<=m;i++){
      read(e[i].a),read(e[i].b),read(e[i].c),read(e[i].d);
      ADD(gi[e[i].b],i),ADD(go[e[i].a],i);
      G::val[i]=e[i].c;
    }
    cnt=m;
    for(i=1;i<K;i++)read(x),read(y),read(z),add(x,y);
    dfs(1),dfs2(1,1);
    for(i=1;i<=n;i++)solve(i);
    G::solve();
    for(i=2;i<=n;i++){
      x=inf;
      for(j=gi[i];j;j=NXT[j])x=min(x,G::d[V[j]]);
      printf("%d\n",x);
    }
    for(i=1;i<=cnt;i++)G::g[i]=G::val[i]=0;
    for(i=1;i<=K;i++)g[i]=size[i]=f[i]=d[i]=son[i]=0;
    for(i=1;i<=n;i++)gi[i]=go[i]=0;
    ED=dfn=G::ed=0;
  }
  return 0;
}

  

时间: 2024-10-24 12:01:58

BZOJ4912 : [Sdoi2017]天才黑客的相关文章

[LOJ#2270][BZOJ4912][SDOI2017]天才黑客

试题描述 SD0062 号选手小 Q 同学为了偷到 SDOI7012 的试题,利用高超的黑客技术潜入了 SDOI 出题组的内联网的中央控制系统,然而这个内联网除了配备有中央控制系统,还为内联网中的每条单向网线设定了特殊的通信口令,这里通信口令是一个字符串,不同网线的口令可能不同.这让小 Q 同学感觉有些棘手, 不过这根本难不倒他,很快他就分析出了整个内联网的结构. 内联网中有 n 个节点(从 1 到 n 标号)和 m 条单向网线,中央控制系统在第 1 个节点上,每条网线单向连接内联网中的某两个节

Luogu P3783 [SDOI2017]天才黑客

题目 调了差不多有10h吧,真的我太难了. 首先一个比较自然的想法是化边为点,每条边拆成一个入点和一个出点,入点到出点连一条长度为这条边的边权的边.同时对于两条边而言,从各自的出点到对方的入点连一条长度为两条边的字符串的\(lcp\)的边. 这样建出来的边数是\(O(m^2)\)的,非常的不优秀. 我们可以发现一件事情:我们把所有字符串按其在trie上的dfs序排个序,设\(l_i=lcp(s_i,s_{i+1})=dep_{lca(s_i,s_j)}\),那么\(lcp(s_i,s_j)=\m

影响Linux发展的四位天才黑客

影响Linux发展的四位天才黑客 相信大家对 Linux 再熟悉不过了.我们都知道 Linux继承自 Unix,但其实他们上一代还有一个 Multics.从最早的 Multics 发展到最早版本的 Linux,用了 28 年.这其中有四位天才级大师的贡献功不可没.现在就大家一起来回顾一下这段历史 操作系统鼻祖——Multics Multics 全称是 MULTiplexed Information and Computing System.维基翻译过来是 多任务信息与计算系统.它是一套分时多任务

天才黑客!17岁打脸乔布斯,20岁搞疯索尼,26岁叫板特斯拉,写2000行代码市值8000万美金

文/创日报 今天说一个屌到飞起的黑客小哥! 扒他的时候创哥就觉得无比的欢快, 因为他的人生用三个字就能概括: “爽!爽!爽!” 不但颜值出众,智商更是卓绝! 89年出生,却把互联网巨头玩弄于股掌间, 17岁仅靠一把螺丝刀,破解了iPhone核心基带, 让iPhone变成了全网通. ▼ 无数人削尖脑袋都挤不进去的 “Google,SpaceX,Facebook” 人家拍拍屁股混了一圈, 说不干就不干! 因为觉得人生太无聊, 顺手破解了索尼的游戏机, 逼的索尼将他告上法庭, 还引发了世!界!级!黑客

SDOI2017 R2 Day2

2018.4.29 Test 时间:7:30~11:30(实际没用多少) 实际得分:0+20+30=50 总结 LOJ总题目链接 T1 BZOJ.4912.[SDOI2017]天才黑客 题目链接 T2 BZOJ.4913.[SDOI2017]遗忘的集合 题目链接 正解生成函数什么的 部分分有点坑 弃了 T3 BZOJ.4914.[SDOI2017]文本校正 题目链接 考试代码 T1 #include <cstdio> #include <cctype> #include <c

George Hotz 才是真正的黑客,他用自己的才智正在改变世界!

今天事儿君要说的是一个年少成名的天才黑客小哥的故事.他是第一个破解初代iPhone的人... 也是第一个破解索尼的PS3的人.... 在各种惹事之后... 终于成熟的他决定隐居之后.... 最近,他决定挑战大公司,自己造了一辆自动驾驶的车.... 事情开始于2007年,小哥的名字叫George Hotz,那一年他只有17岁. 2007年,第一台iphone面世,当时AT&T是独家运营商,锁网. 只有用这个公司的网络才能用爱疯. 当年,他钻研一番之后,成功解锁! 让AT&T之外的用户也能使用

历史上留下浓重一笔的黑客们

在互联网发展早期,黑客往往是一些因为兴趣而惹祸上身的天才少年,但随着互联网经济成为世界经济的重要一部分,让很多人对黑客产生了兴趣,因此今天很多黑客入侵电脑通常就是为了钱,而据一些专家表示,世界上一些顶级网络骗子每年收入可达一亿美元. 为此国外网站businessinsider罗列了十位让你生活可以立马变得苦不堪言的黑客,趁这次机会,就让我们一起看下那些年都有哪些黑客在历史上留下了浓重的一笔. 第一位:盗刷金额最大的黑客Albert Gonzalez 作为一名黑客,Albert Gonzalez在

非常值得一看的6部黑客电影,你看过哪几部?

摘要: 1.<黑客帝国>影片讲述了,二十一世纪初,人工智能的技术有重大的突破,计算机能够自行学习,代替人类做很多事,但是计算机却发展出自我意识,不愿再听命于人类.人类企图关闭电源,结束计算机的自我意识,计算机却 ... 1.<黑客帝国>影片讲述了,二十一世纪初,人工智能的技术有重大的突破,计算机能够自行学习,代替人类做很多事,但是计算机却发展出自我意识,不愿再听命于人类.人类企图关闭电源,结束计算机的自我意识,计算机却抢先一步宰制人类的命运,培植人类做为电力的来源.每一个人从出生开

【转】操作系统Unix、Windows、Mac OS、Linux的故事

电脑,计算机已经成为我们生活中必不可少的一部分.无论是大型的超级计算机,还是手机般小巧的终端设备,都跑着一个操作系统.正是这些操作系统,让那些硬件和芯片得意组合起来,让那些软件得以运行,让我们的世界在科技的领域里一次又一次的享受生活 我们熟知的操作系统大概都是windows系列,近年来Apple的成功,让MacOS也逐渐走进普通用户.在服务器领域,恐怕Linux是无人不知无人不晓.他们都是操作系统,也在自己的领域里独领风骚.这都还得益于另外一个古董级别的操作系统--Unix,虽然说古董级别,只是