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)=\min\limits_{k\in[i,j)}l_k\)。
那么一种可行的优化建图是利用单调栈求出各个\(l_i\)被取到的区间,然后线段树优化建图,边数为\(O(m\log^2m)\)。
但是我们有更加优秀的优化建图的方法。
每个\(l_i\)代表\(\le i\)的出点可以通过\(l_i\)的代价走到\(>i\)的入点,\(>i\)的出点可以通过\(l_i\)的的代价走到\(\le i\)的入点。
直接连就是\(O(n^3)\)的了。
我们可以这样连:
\(i\)的入点和出点分别与\(i+1\)的入点和出点连一条\(0\)的边。
对于\(\le i\)的出点可以通过\(l_i\)的代价走到\(>i\)的入点,连\(i\)的出点到\(i+1\)的入点边权为\(l_i\)的边。
对于\(>i\)的出点可以通过\(l_i\)的的代价走到\(\le i\)的入点这种边,我们可以把\(i\)的入点和出点都拆成两个,一对处理上面那种,另一对处理下面这种。
所以另一对就这么连:
\(i\)的入点和出点分别与\(i-1\)的入点和出点连一条\(0\)的边。
对于\(>i\)的出点可以通过\(l_i\)的代价走到\(\le i\)的入点,连\(i+1\)的出点到\(i\)的入点边权为\(l_i\)的边。
那么每条边的两个入点到两个出点都要连长度为这条边边权的边。
最后建一个超级原点,到所有从\(1\)出发的边的入点连一条长度为\(0\)的边,跑一遍最短路。
对于每一个点在原图中的最短路,就是所有原图中指向它的点的出点的最短路。
码风比较清奇?凑合着看吧。

#include<bits/stdc++.h>
#define ll long long
#define pi pair<int,int>
#define Pi pair<ll,int>
#define pb push_back
#define fi first
#define se second
using namespace std;
int read()
{int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
void swap(int &a,int &b)
{a^=b^=a^=b;}
const int N=20007;
int n,m,k,dfn[N],dep[N];
namespace trie
{
    int fa[N][18],T;vector<int>E[N];
    void clear()
    {for(int i=1;i<=k;++i)E[i].clear();memset(fa,0,sizeof fa),T=0;}
    void add(int w,int v,int u)
    {E[u].pb(v);}
    void dfs(int u)
    {for(int i=0;fa[u][i];++i)fa[u][i+1]=fa[fa[u][i]][i];dfn[u]=++T;for(int v:E[u])if(v^fa[u][0])dep[v]=dep[u]+1,fa[v][0]=u,dfs(v);}
    int lca(int u,int v)
    {if(dep[u]<dep[v])swap(u,v);for(int d=dep[u]-dep[v],i=0;d;d>>=1,++i)if(d&1)u=fa[u][i];if(u==v)return u;for(int i=17;~i;--i)if(fa[u][i]^fa[v][i])u=fa[u][i],v=fa[v][i];return fa[u][0];}
    void build()
    {dfs(1);}
}
namespace graph
{
    const int M=50007,V=M*4;
    int t,s,p[V],vis[V];ll dis[V];vector<pi>e[V];vector<int>a[M],b[M],c[M],d[M],vec;priority_queue<Pi>q;
    int cmp(int i,int j)
    {return dfn[p[i]]<dfn[p[j]];}
    void clear()
    {for(int i=1;i<=s+1;++i)e[i].clear(),a[i].clear(),b[i].clear(),c[i].clear(),d[i].clear();t=0;}
    void add(int u,int v,int w)
    {e[u].pb(pi(v,w));}
    void ins(int pos,int w,int v,int u)
    {
    if(u==1)add(s,t+1,0),add(s,t+3,0);for(int i=1;i<=4;i++)p[t+i]=pos;
        add(t+1,t+2,w),add(t+1,t+4,w),add(t+3,t+4,w),add(t+3,t+2,w),a[u].pb(++t),b[v].pb(++t),c[u].pb(++t),d[v].pb(++t);
    }
    void build()
    {
    for(int i,j,k,u=1,w;u<=n;++u)
    {
        sort(a[u].begin(),a[u].end(),cmp),sort(b[u].begin(),b[u].end(),cmp),sort(c[u].begin(),c[u].end(),cmp),sort(d[u].begin(),d[u].end(),cmp);
        for(i=0;i+1<a[u].size();++i)add(a[u][i],a[u][i+1],0);
        for(i=0;i+1<b[u].size();++i)add(b[u][i],b[u][i+1],0);
        for(i=0;i+1<c[u].size();++i)add(c[u][i+1],c[u][i],0);
        for(i=0;i+1<d[u].size();++i)add(d[u][i+1],d[u][i],0);
        vec.resize(a[u].size()+b[u].size()),merge(b[u].begin(),b[u].end(),a[u].begin(),a[u].end(),vec.begin(),cmp);
        for(k=i=j=0;k+1<vec.size();++k)
        {
        (vec[k]&1?++j:++i),w=dep[trie::lca(p[vec[k]],p[vec[k+1]])];
        if(i&&j!=a[u].size()) add(b[u][i-1],a[u][j],w);
        if(i!=d[u].size()&&j) add(d[u][i],c[u][j-1],w);
        }
    }
    }
    void dij()
    {
    memset(dis,0x3f,sizeof dis),memset(vis,0,sizeof vis),q.push(Pi(dis[s]=0,s));
    for(int u;!q.empty();)
    {
        u=q.top().se,q.pop();if(vis[u])continue;vis[u]=1;
        for(auto[v,w]:e[u]) if(dis[v]>dis[u]+w)dis[v]=dis[u]+w,q.push(Pi(-dis[v],v));
    }
    }
    void solve()
    {for(int i=2;i<=n;++i){ll ans=1e18;for(int x:b[i])ans=min(ans,dis[x]);for(int x:d[i])ans=min(ans,dis[x]);printf("%lld\n",ans);}}
}
void solve()
{
    n=read(),m=read(),k=read(),graph::s=4*m+1,trie::clear(),graph::clear();
    for(int i=1;i<=m;++i)graph::ins(read(),read(),read(),read());
    for(int i=2;i<=k;++i)trie::add(read(),read(),read());
    trie::build(),graph::build(),graph::dij(),graph::solve();
}
int main()
{for(int T=read();T;--T)solve();return 0;}

原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11791278.html

时间: 2024-10-17 06:30:27

Luogu P3783 [SDOI2017]天才黑客的相关文章

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

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

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$的代价互相访问. 建立一排前缀虚点和后缀虚点然后对应前后缀之间连边即可

[Luogu 3707] SDOI2017 相关分析

[Luogu 3707] SDOI2017 相关分析 <题目链接> 前言 Capella 和 Frank 一样爱好天文学. 她常在冬季的夜晚,若有所思地望着东北方上空的五边形中,最为耀眼的一个顶点. 那一抹金黄曾带给她多少美好的遐想! 直到有一天,她做了这一题,并饱受线段树的折磨. 概述 这是一道区间操作的题目,解法有线段树与分块等. 题主选择线段树进行讲解(因为没用分块写这题). 准备与计算答案 首先要知道,线段树需要维护的数值有哪些. 先来看题目中所给的公式. \(\bar x = \fr

影响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” 人家拍拍屁股混了一圈, 说不干就不干! 因为觉得人生太无聊, 顺手破解了索尼的游戏机, 逼的索尼将他告上法庭, 还引发了世!界!级!黑客

luogu P3703 [SDOI2017]树点涂色

luogu 看到操作1,应该学过lct的都知道这个等价于access操作,所以可以考虑用lct维护,相同颜色的一条链就用lct上的一棵splay维护,每次操作1就\(access(x)\) 要回答操作2和操作3,都要求出某点到根的颜色段数.考虑\(access(x)\)过程中会改变一些点的颜色段数,当某条边变成虚边后,那么对应儿子子树内所有点的颜色数都加\(1\),当某条边变成实边后,对应儿子子树内所有点的颜色数都减\(1\),这个不理解可以手动模拟access.然后操作二答案为\(a_x+a_

luogu P3707 [SDOI2017]相关分析

传送门 对于题目要求的东西,考虑拆开懒得拆了 ,可以发现有\(\sum x\sum y\sum x^2\sum xy\)四个变量影响最终结果,考虑维护这些值 下面记\(l,r\)为区间两端点 首先是区间加操作,可以这样维护\[\sum(x+s)=\sum x+(r-l+1)s\]\[\sum(y+s)=\sum y+(r-l+1)s\]\[\sum(x+s)^2=\sum x^2+2s\sum x+(r-l+1)s^2\]\[\sum(x+s)(y+t)=\sum xy+s\sum y+t\su

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之外的用户也能使用