zoukankan      html  css  js  c++  java
  • luogu P3783 [SDOI2017]天才黑客

    LINK:SDOI2017天才黑客

    给出一张图 一颗字符串树 一张图上每条边有边权和字符串 经过一条边的代价是 之前的字符串和当前字符串的LCP+当前这条边的边权。

    问这张图上从1到任意点的最短路。

    既然询问最短路 我们当然可以dij来跑了但是我们到达每个点的状态有nk种状态 k是字符串树的节点个数 考虑存在nk的状态数 每个状态数进出队一次。

    顺便再考虑一下最短路转移时怎么做?求出字典树上两个点表示的字符串的LCP 考虑把字典树变形 变成SAM或者trie树 然后可以发现LCP其实是树上的LCA表示的len。

    所以每次转移我们可以降到logn。可以获得70分的好成绩.

    到底变成trie树还是SAM呢?好吧题目中给出的就是Trie树所以不存在这个问题 我们直接O(1)LCA即可。

    本着一定可以通过这道题的想法 所以说这道题的状态数必然会可以降下来。

    本着拥有这样的想法 可以发现必须对我们的图有所改变 考虑一下有什么地方导致状态有这么多?原因其实还是图的原因虽然图上还是m条边 但是在转移的时候的边的不同造成当前字符串不同 同时对于不同的字符串同一条边 我们进行不同的转移所以看起来是m条边 但是边被我们无意间就扩充了。

    考虑不进行这样的判断让其自己跑我们就不需要管那么多状态了这样起码把状态数优化了 但是图怎么办 为了还是满足原来的LCP的条件我们只能把边化成点 由于边权的存在我们需要将边权拆成两个点 出点和入点 对于两条边相连的状态显然是一个出点连一个入点 边权为他们的LCP。

    这样我们把状态数降下来了 图也搞好了但是考虑到边数问题 考虑一张二分图这样边数为(m^2)还是爆炸。

    这个时候考虑对于每一个出点进行连边的时候 我们可以发现连的是一些点 而这些点最多有k种 从数量上来看总和m条。

    所以对于边权一样的边我们可以进行压缩。

    采用前后缀连边 类似于后缀数组的h数组 就可以完成 边的数量级仍然为O(m).

    const int MAXN=100010,maxn=1000010;
    int T,n,m,k,len,cnt,id,top;
    int w[MAXN],dfn[MAXN],s[maxn],pl[MAXN],pr[MAXN],wl[MAXN],wr[MAXN],f[MAXN][20],d[MAXN];
    int dis[maxn],v[maxn],lin[maxn],ver[maxn<<1],nex[maxn<<1],e[maxn<<1],vis[maxn];
    vector<int>in[maxn],out[maxn];
    priority_queue<pii>q;
    inline int cmp(int x,int y){return dfn[w[abs(x)]]<dfn[w[abs(y)]];}
    inline void add(int x,int y,int z)
    {
    	ver[++len]=y;
    	nex[len]=lin[x];
    	lin[x]=len;
    	e[len]=z;
    }
    inline void dfs(int x)
    {
    	dfn[x]=++id;
    	for(int i=1;i<=15;++i)f[x][i]=f[f[x][i-1]][i-1];
    	for(int i=lin[x];i;i=nex[i])
    	{
    		int tn=ver[i];
    		d[tn]=d[x]+1;f[tn][0]=x;
    		dfs(tn);
    	}
    }
    inline int LCA(int x,int y)
    {
    	if(d[x]<d[y])swap(x,y);
    	for(int i=15;i>=0;--i)
    		if(d[f[x][i]]>=d[y])x=f[x][i];
    	if(x==y)return x;
    	for(int i=15;i>=0;--i)
    		if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    	return f[x][0];
    }
    inline void change(int x)
    {
    	top=0;
    	for(int i=0;i<in[x].size();++i)s[++top]=in[x][i];
    	for(int i=0;i<out[x].size();++i)s[++top]=-out[x][i];
    	sort(s+1,s+1+top,cmp);
    	for(int i=1;i<=top;++i)
    	{
    		pl[i]=++cnt;pr[i]=++cnt;
    		wl[i]=++cnt;wr[i]=++cnt;
    		if(i>1)
    		{
    			add(pl[i-1],pl[i],0);add(pr[i-1],pr[i],0);
    			add(wl[i],wl[i-1],0);add(wr[i],wr[i-1],0);
    		}
    		if(s[i]>0)add(s[i],pl[i],0),add(s[i],wl[i],0);
    		else s[i]=-s[i],add(pr[i],s[i],0),add(wr[i],s[i],0);
    	}
    	for(int i=1;i<top;++i)
    	{
    		int ww=d[LCA(w[s[i]],w[s[i+1]])]-1;
    		//cout<<ww<<endl;
    		add(pl[i],pr[i+1],ww);add(wl[i+1],wr[i],ww);
    	}
    }
    inline void dij()
    {
    	while(q.size())
    	{
    		int x=q.top().S;q.pop();
    		if(vis[x])continue;
    		vis[x]=1;
    		for(int i=lin[x];i;i=nex[i])
    		{
    			int tn=ver[i];
    			if(dis[tn]>dis[x]+v[tn]+e[i])
    			{
    				dis[tn]=dis[x]+v[tn]+e[i];
    				q.push(mk(-dis[tn],tn));
    			}
    		}
    	}
    }
    int main()
    {
    	//freopen("1.in","r",stdin);
    	get(T);
    	while(T--)
    	{
    		get(n);get(m);get(k);len=id=0;cnt=m;
    		rep(1,maxn-10,i)dis[i]=INF,vis[i]=0,lin[i]=0,v[i]=0,in[i].clear(),out[i].clear();;
    		rep(1,m,i)
    		{
    			int x,y;
    			get(x);get(y);
    			get(v[i]);get(w[i]);
    			if(x==1)q.push(mk(-(dis[i]=v[i]),i));
    			in[y].pb(i);out[x].pb(i);
    		}
    		rep(1,k-1,i)
    		{
    			int x;get(x);
    			add(x,read(),0);
    			read();
    		}
    		len=0;d[1]=1;dfs(1);
    		rep(1,k,i)lin[i]=0;
    		rep(1,n,i)change(i);
    		dij();
    		rep(2,n,i)
    		{
    			int ans=INF;
    			rep(0,in[i].size()-1,j)ans=min(ans,dis[in[i][j]]);
    			put(ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(2月16日)
    优步UBER司机全国各地奖励政策汇总 (2月15日-2月21日)
    优步UBER司机全国各地奖励政策汇总 (2月8日-2月14日)
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(2月7日~2月13日)
    成都Uber优步司机奖励政策(2月7日)
    file does not exist 阿里云OSS图片上传遇到的问题
    redis.conf 配置项说明
    redis 五大数据类型的常用指令
    redis配置外部访问
    linux安装redis
  • 原文地址:https://www.cnblogs.com/chdy/p/12486546.html
Copyright © 2011-2022 走看看