zoukankan      html  css  js  c++  java
  • 传纸条(scrip)

    传纸条(scrip)

    题目背景

    Awson是某国际学校信竞组的一只菜鸡。每次竞赛考试都只能垫底。终于有一天,他决定不再苟活,发挥他的人脉优势,准备在一次竞赛考试时传纸条作弊。

    题目描述

    他预先知道了考试时机房人数N(1<=N<=10000),自己编号为1,并且由于他十分地交际,所以能够确保所有人能为他提供答案。为了传递纸条,他会开动脑筋,想出M(0<=M<=100000)种单个可行方案。每种单个方案不一定与自己有关,因为他可以间接地从别人那获得他人的答案。每种方案已知三个数据U,V,C(1<=U,V<=N;1<=C<=1000000)表示从U到V有一种可行方案,其代价为C,且方案是双向的,即U可以传纸条给V且V也可以传纸条给U。由于作弊是高风险的事情,他决定考前预谋好总的方案。他想知道:

    (1)团结所有人(即每个人都能够互相联系)所需要的最小代价和。

    (2)基于(1),他会给出Q(1<=Q<=10000)个询问,每个询问有三个数据OPT,X,Y(OPT=0 or 1;1<=X,Y<=N),询问有两种类型:

    OPT=0时:询问X到Y的路径上单个最大代价的值;

    OPT=1时:询问X到Y的路径上的总代价。

    但如果不存在(1)方案,即他不能团结起所有人,那么他这场考试就又失败了,他就会无限地堕落下去,请输出”OVER!”(半角字符,不含引号),并忽略之后的询问。

    由于他还有重要的事情要做,所以这个任务交给了你,怎么样,应该不难吧?

    (请阅读样例及其说明以便更好地了解题意)

    输入输出格式

    输入格式:

    第1行:两个整数N,M

    第2~M+1行:每行三个整数Ui,Vi,Ci

    第M+2行:一个整数Q

    第M+3~M+Q+2行:每行三个整数OPTi,Xi,Yi

    输出格式:

    有两种情况:

    若不存在(1)方案,输出共1行,第1行为”OVER!”(半角字符,不含引号);

    若存在,输出共Q+1行,第1行一个整数,表示团结所有人所需要的最小代价和,第2~Q+1行每行一个整数,代表每个询问的结果。

    输入输出样例

    输入样例:

    7 12

    1 4 994

    1 2 999

    1 2 1

    1 3 2

    1 6 998

    2 4 4

    2 5 3

    3 7 5

    3 6 6

    4 5 995

    5 7 996

    6 7 997

    10

    1 1 4

    0 1 4

    1 1 7

    0 1 6

    1 4 6

    0 5 7

    1 2 4

    0 3 5

    1 6 7

    0 4 5

    输出样例:

    21

    5

    4

    7

    6

    13

    5

    4

    3

    11

    4

    说明

    样例解释:

    路径1<—>4上,所有的单个方案代价分别为1,4。则对于第一组询问(1,1,4),代价和为1+4=5;对于第二组询问(0,1,4),其路径上单个最大的代价为4。
    团结所有人的方案在图中用红色表示,则所需要的最小代价和为1+2+3+4+5+6=21。

    其余同理。

    数据规模:

    30%的数据:1<=N,Q<=1000

    50%的数据:1<=N,Q<=5000

    100%的数据:1<=N,Q<=10000,0<=M<=10×N,所有数据保证不会超过长整型(C++中的int),保证每种单个方案的代价各不相同。

    题解:

    正解Kruskal+LCA

    用Kruskal求出图的最小生成树,转化为有根树之后套LCA模板。

    本来想强制在线的,但数据太水你会发现就算退化成链每次直接遍历都不会超时。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    typedef long long lol;
    lol n,m,l,mmax,ans,tot;//n<=10000;m<=100000;l<=10000
    struct student{lol u,v,c;}a[100005];
    bool cmp(const student a,const student b){return a.c<b.c;}//输入边和排序
    lol head[10001],size=1;
    struct node{lol next,to,dis;}edge[200005];
    void putin(lol from,lol to,lol dis){size++;edge[size].to=to;edge[size].next=head[from];edge[size].dis=dis;head[from]=size;}
    void in(lol from,lol to,lol dis){putin(from,to,dis);putin(to,from,dis);}//建树 
    lol father[10005];
    lol find(lol x){if(father[x]==x)return x;else return father[x]=find(father[x]);}//并查集
    lol fa[10005][25],vis[10005],depth[10005],dis[10005][25],dist[10005][25];
    void dfs(lol r)
    {
        vis[r]=1;lol i;
        for(i=head[r];i!=-1;i=edge[i].next)
        {
            lol y=edge[i].to;
            if(!vis[y]){depth[y]=depth[r]+1;fa[y][0]=r;dist[y][0]=dis[y][0]=edge[i].dis;dfs(y);}
        }
    }
    void make()
    {
        lol i,j,len=log2(n);
        for(j=1;j<=len;j++)
        {
            for(i=1;i<=n;i++)
            {
                dis[i][j]=max(dis[fa[i][j-1]][j-1],dis[i][j-1]);
                dist[i][j]=dist[fa[i][j-1]][j-1]+dist[i][j-1];
                fa[i][j]=fa[fa[i][j-1]][j-1];
            }
        }
    }
    void RMQ(lol x,lol y)
    {
        mmax=0;ans=0;
        lol i,op=log2(n);
        if(depth[x]<depth[y])swap(x,y);
        for(i=op;i>=0;i--)
        if(depth[fa[x][i]]>=depth[y])
        {
            mmax=max(mmax,dis[x][i]);
            ans+=dist[x][i];
            x=fa[x][i];
        }
        if(x!=y)
        {
            for(i=op;i>=0;i--)
            if(fa[x][i]!=fa[y][i])
            {
                mmax=max(mmax,max(dis[x][i],dis[y][i]));
                ans+=dist[x][i]+dist[y][i];
                x=fa[x][i];y=fa[y][i];
            }
            ans+=dist[x][0]+dist[y][0];
            mmax=max(mmax,max(dis[x][0],dis[y][0]));
            x=fa[x][0];y=fa[y][0];
        }
        return;
    }
    lol gi()
    {
        lol ans=0,f=1;
        char i=getchar();
        while(i<'0'||i>'9'){if(i=='-')f=-1;i=getchar();}
        while(i>='0'&&i<='9'){ans=ans*10+i-'0';i=getchar();}
        return ans*f;
    }
    int main()
    {
        freopen("scrip.in","r",stdin);
        freopen("scrip.out","w",stdout);
        lol i;
        n=gi();m=gi();
        memset(head,-1,sizeof(head));
        for(i=1;i<=n;i++)father[i]=i;//初始化并查集
        for(i=1;i<=m;i++){a[i].u=gi();a[i].v=gi();a[i].c=gi();}//输入边 
        sort(a+1,a+m+1,cmp);//排序
        for(i=1;i<=m;i++)
        {
            lol p=find(a[i].u),q=find(a[i].v);
            if(p!=q){father[p]=q;in(a[i].u,a[i].v,a[i].c);tot+=a[i].c;}
        }
        printf("%lld
    ",tot);
        depth[1]=1;dfs(1);make();
        l=gi();
        for(i=1;i<=l;i++)
        {
            lol s=gi(),u=gi(),v=gi();RMQ(u,v);
            if(s==0)printf("%lld
    ",mmax);//单个最大
            else if(s==1)printf("%lld
    ",ans);//求路径和
        }
        return 0;
    }
  • 相关阅读:
    人物-作家-马克·吐温:马克·吐温
    人物-发明家-特斯拉:尼古拉·特斯拉
    视觉暂留-Info:这些神奇的“视觉暂留”动画,每一幅都让人拍案叫绝!
    视觉暂留:余晖效应/视觉暂留
    mingetty
    mesg
    md5sum
    man.conf
    man
    makemap
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/7257669.html
Copyright © 2011-2022 走看看