BZOJ 5415: [Noi2018] Tree Reconstruction return journey kruskal

title

\ (~ \)
BZOJ 5415
LUOGU 4768
Long title of it, do not want to put up. .

analysis

Two little emotion:

  1. Because I heard this question, some heavyweights \ (Ag \ to Cu \) , because with the \ (SPFA \) , so, after experiencing no negative side of the map, or use \ (Dijkstra \) it.
  2. \ (kruskal \) reconstructed tree is actually regarded as belonging to the rare knowledge of it, \ (BZOJ \) on only \ (Network \) referred to this algorithm, so learning algorithm really seriously, and this time, brush title amount represents something up.

Officially Solution:
This question is to use \ (kruskal \) reconstruction of the tree, and why? Nature dictates. \ (kruskal \) reconstruct the tree has the following good properties:

  • Tree leaf node point other than the edge corresponds to the original spanning tree, the leaf nodes is a node on the original spanning tree.
  • Because creating a new point of order and the size of the original spanning tree right on top of about it can be found, from each point to the root node (except leaf nodes) point to the right in order to access point is monotonous.
  • For \ (Kruskal \) algorithm is greedy in nature, two points \ (X \) and \ (Y \) a \ (LCA \) point to the right thereof corresponds to the minimum spanning tree bottleneck.
  • In fact, this tree is a binary heap.

This question is then how to construct \ (kruskal \) reconstruction of the tree?
The shortest length buttoned up, then left altitude, use this to get myself, to the elevation of the first key on the side were descending order, the construction of \ (kruskal \) reconstruction tree .

For each subtree, if the query is below the water line of the sub-tree root, then when all the sub-tree leaf nodes in the tree is communication . That Fengyun subtree optionally a point of departure, point to the other sub-tree do not need to spend.

Suppose that for the current inquiry, we found the root node a subtree \ (the X-\) (satisfying \ (d [x]> p \) and \ (d [fa [x] ] <= p \) and the starting point \ ( Y \) in the sub-tree), from the time \ (Y \) departing direct access to any sub-tree of a leaf node.

So we need to select a number from 1 point to spend a minimum, so this will use from a number of leaf nodes \ (Dijkstra \) deal with a minimum spend all point to a good point, This question is even finished.

Complete idea to the past, please refer ldxcaicai of, hehe:
then stroked a stroke ideas.

  1. We first requires the minimum cost per point 1 to point directly to the \ (Dijsktra + \) Shortest pretreatment.
  2. Then to build a \ (kruskal \) reconstruction of the tree, and then maintained at each time point as the root node in the subtree minimum cost 1-point distance, this tree after completing construction of a simple \ (dfs \) to get .
  3. The last point is how to find \ (the X-\) , then we make an important algorithm debut: multiplication algorithm. Direct plus point right \ (> p \) is restricted to the trees can multiply.

code

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int maxn=4e5+10,maxm=8e5+10,inf=0x3f3f3f3f;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
    x=0;
    T f=1, ch=getchar();
    while (!isdigit(ch) && ch^'-') ch=getchar();
    if (ch=='-') f=-1, ch=getchar();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    x*=f;
}

char Out[1<<24],*fe=Out;
inline void flush() { fwrite(Out,1,fe-Out,stdout); fe=Out; }
template<typename T>inline void write(T x)
{
    if (!x) *fe++=48;
    if (x<0) *fe++='-', x=-x;
    T num=0, ch[20];
    while (x) ch[++num]=x%10+48, x/=10;
    while (num) *fe++=ch[num--];
    *fe++='\n';
}

int vc[maxm<<1],Nc[maxm<<1],hc[maxn<<1],lc;
inline void addc(int x,int y)
{
    vc[++lc]=y,Nc[lc]=hc[x],hc[x]=lc;
}

struct Orz{int x,y,l,a;}e[maxm],p[maxn<<1];
inline bool cmp(Orz c,Orz d)
{
    return c.a>d.a;
}

int fa[maxn<<1];
inline int get(int x)
{
    return fa[x]==x?x:fa[x]=get(fa[x]);
}

int n,m,cnt,sum;
inline void Kruskal()
{
    cnt=n,sum=0;
    for (int i=1; i<=(n<<1); ++i) fa[i]=i;
    sort(e+1,e+m+1,cmp);
    for (int i=1; i<=m; ++i)
    {
        int x=get(e[i].x),y=get(e[i].y);
        if (x==y) continue;
        addc(++cnt,x),addc(cnt,y);
        fa[x]=fa[y]=cnt;
        p[cnt].a=e[i].a;
        if (++sum==n-1) break;
    }
}

int ver[maxm],edge[maxm],Next[maxm],head[maxn],len;
inline void add(int x,int y,int z)
{
    ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
    ver[++len]=x,edge[len]=z,Next[len]=head[y],head[y]=len;
}

int dist[maxn];
bool vis[maxn];
inline void Dijkstra(int s)
{
    memset(dist,0x3f,sizeof(dist));
    memset(vis,0,sizeof(vis));
    priority_queue<pii,vector<pii>,greater<pii> >q;
    q.push(make_pair(0,s)),dist[s]=0;
    while (!q.empty())
    {
        int x=q.top().second;
        q.pop();
        if (vis[x]) continue;
        vis[x]=1;
        for (int i=head[x]; i; i=Next[i])
        {
            int y=ver[i],z=edge[i];
            if (dist[y]>dist[x]+z)
            {
                dist[y]=dist[x]+z;
                q.push(make_pair(dist[y],y));
            }
        }
    }
    for (int i=1; i<=n; ++i) p[i].l=dist[i];
}

int f[maxn][20],d[maxn];
inline void dfs(int x,int pa)
{
    d[x]=d[pa]+1,f[x][0]=pa;
    for (int i=1; i<=19; ++i) f[x][i]=f[f[x][i-1]][i-1];
    for (int i=hc[x]; i; i=Nc[i])
    {
        int y=vc[i];
        dfs(y,x);
        p[x].l=min(p[x].l,p[y].l);
    }
}

inline int query(int x,int y)
{
    for (int i=19; i>=0; --i)
        if (d[x]-(1<<i)>0 && p[f[x][i]].a>y) x=f[x][i];
    return p[x].l;
}

inline void Clear()
{
    memset(f,0,sizeof(f));
    memset(d,0,sizeof(d));
    memset(head,0,sizeof(head));
    memset(hc,0,sizeof(hc));
    len=lc=0;
}

int main()
{
    int T;read(T);
    while (T--)
    {
        Clear();
        read(n);read(m);
        for (int i=1; i<=m; ++i) read(e[i].x),read(e[i].y),read(e[i].l),read(e[i].a),add(e[i].x,e[i].y,e[i].l);
        for (int i=n+1; i<=(n<<1); ++i) p[i].l=inf;
        Dijkstra(1);
        int Q,K,S;
        read(Q);read(K);read(S);
        Kruskal();
        dfs(cnt,0);
        int lastans=0;
        while (Q--)
        {
            int v,p;read(v);read(p);
            int x=(v+lastans*K-1)%n+1,y=(p+lastans*K)%(S+1);
            write(lastans=query(x,y));
        }
    }
    flush();
    return 0;
}

Guess you like

Origin www.cnblogs.com/G-hsm/p/11318201.html