zoukankan      html  css  js  c++  java
  • BZOJ5415 [NOI2018] 归程

    今天也要踏上归程了呢~(题外话

    kruskal重构树!当时就听学长们说过是重构树辣所以做起来也很快233

    就是我们按照a建最大生成树 这样话呢我们就可以通过生成树走到尽量多的点啦

    然后呢就是从这个子树内走到1的最短路 提前处理出来然后就是子树最小值啦w

    附代码。(些许丑陋(

    //Love and Freedom.
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #define ll long long
    #define inf 20021225
    #define N 400010
    #define M 800010
    using namespace std;
    struct edge{int x,y,v;}g[M];
    struct edg{int to,lt,v;}e[M],t[N];
    struct node
    {
        int id,v;
        node(){}
        node(int _id,int _v){id=_id,v=_v;}
    };
    bool operator <(node a,node b){return a.v>b.v;}
    priority_queue<node> q;
    int cnt,in[N];
    void add(int x,int y,int l,int a)
    {
        e[++cnt].to=y; e[cnt].lt=in[x]; e[cnt].v=l; in[x]=cnt;
        e[++cnt].to=x; e[cnt].lt=in[y]; e[cnt].v=l; in[y]=cnt;
        g[cnt>>1].x=x; g[cnt>>1].y=y; g[cnt>>1].v=a;
    }
    void tree(int x,int y)
    {
        t[++cnt].to=y; t[cnt].lt=in[x]; in[x]=cnt;
    }
    int bel[N],n,val[N],m; bool vis[N];
    int find(int x)
    {
        //printf("%d %d
    ",x,bel[x]);
        if(bel[x]==x)    return x;
        return bel[x]=find(bel[x]);
    }
    void dijkstra()
    {
        memset(vis,0,sizeof(vis));
        memset(val,48,sizeof(val)); val[1]=0;
        q.push(node(1,val[1]));
        while(!q.empty())
        {
            node tmp = q.top(); q.pop();
            if(vis[tmp.id])    continue;
            vis[tmp.id]=1; int x=tmp.id;
            for(int i=in[x];i;i=e[i].lt)
            {
                int y=e[i].to; if(val[y]>val[x]+e[i].v)
                    val[y]=val[x]+e[i].v,q.push(node(y,val[y]));
            }
        }
    }
    bool cmp(edge x,edge y){return x.v>y.v;}
    int poi;
    int mn[N],f[N][18];
    void kruskal()
    {
        //memset(bel,0,sizeof(bel));
        sort(g+1,g+m+1,cmp); memset(mn,48,sizeof(mn));
        memset(in,0,sizeof(in)); cnt=0; poi=n;
        for(int i=1;i<=m;i++)
        {
            int x=g[i].x,y=g[i].y;
            int fx=find(x),fy=find(y);
            if(fx==fy)    continue;
            val[++poi]=g[i].v;
            tree(poi,fx); tree(poi,fy);
            bel[fx]=bel[fy]=poi;
        }
    }
    void dfs(int x)
    {
        vis[x]=1;
        for(int i=1;i<18;i++)
            f[x][i]=f[f[x][i-1]][i-1];
        for(int i=in[x];i;i=t[i].lt)
        {
            int y=t[i].to; f[y][0]=x;
            dfs(y); mn[x]=min(mn[x],mn[y]);
        }
        if(x<=n)    mn[x]=val[x];
    }
    int getans(int x,int w)
    {
        for(int i=17;~i;i--)
            if(val[f[x][i]]>w)    x=f[x][i];
        //printf("%d
    ",val[x]);
        return mn[x];
    }
    int main()
    {
        int T;scanf("%d",&T);
        while(T--)
        {
            memset(in,0,sizeof(in)); cnt=0; 
            scanf("%d%d",&n,&m); int u,v,l,a;
            for(int i=1;i<=2*n;i++)    bel[i]=i;
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d%d%d",&u,&v,&l,&a);
                add(u,v,l,a);
            }
            dijkstra(); kruskal(); memset(vis,0,sizeof(vis));
            for(int i=1;i<2*n;i++)    if(!vis[i])    dfs(find(i));
            int Q,k,s,lastans=0,p;
            scanf("%d%d%d",&Q,&k,&s); val[0]=0;
            while(Q--)
            {
                scanf("%d%d",&v,&p);
                v=(v+k*lastans-1)%n+1; p=(p+k*lastans)%(s+1);
                printf("%d
    ",lastans=getans(v,p));
            }
        }
        
        return 0;
    }
    View Code
  • 相关阅读:
    Tarjan专题
    Catalan数
    状压DP
    威尔逊定理证明:
    【fzoj 2376】「POJ2503」Babelfish
    Android 源码
    Android实现推送方式解决方案
    Android apk 签名
    圆角的实现
    Android 资源
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/10386700.html
Copyright © 2011-2022 走看看