• Teleportation(tel)


    Teleportation(tel)

    题目描述

     

     Zy大帝拥有n个星球,因为距离非常遥远,所以Zy在他所居住的1号星球和他的军事基地霸中所在的2号星球建造了两个传送门,这样从1号星球到2号星球就只需要250分钟,回去也一样(双向)。由于科技的发展,各个星球陆陆续续建造了和自己居民最经常去的星球之间的传送门,并且他们的传送门只需要1个小时(真快啊!),他们发现和别的星球建设传送门对促进经济发展有很大的帮助,于是向和其他所有星球建设传送门发展,Zy突然发现两两星球的传送门的建设会威胁到他的安全,可是他又想促进自己帝国的发展,于是他请到了他精心培养的你,希望你能帮他解决这个难题。

     

     

     

    输入

     

    第1行为两个整数n(2<=n<=40000)和m(0<=m<=1000000),n表示星球数,m 表示其他星球已经建造的传送门的对数(传送门都是两两建造的)(不包括Zy在1号和2号的)。

     

    接下来m行每行两个由空格隔开的整数想x,y(2<=x,y<=40000),表示这两个星球建造了传送门连接。

     

     

    输出

     

    还能让多少对传送门建造,但又不会比Zy从1号星球到2号星球快(就是说增加传送门后,从1号星球到2号星球还是Zy的传送门最快)。

     

     

    样例输入

    10 10
    1 3
    3 5
    5 7
    7 9
    2 9
    1 4
    4 6
    6 8
    8 10
    2 10

    样例输出

    10

    提示

     

    实线连接的是已经造好传送门的两星球,虚线连接表示可以增加建造的传送门两星球。可以看出,建造了10对以后,从1号到2号星球还是Zy的250分钟最快。

     

     

     

    来源

    Poi2010


    solution

    分层图。

    当时考场傻了,没考虑周全。

    设1为S,2为T

    题目要求S~T的最短路长度<=5,同时最大化总边数。

    设与S一步的点有a个,T一步的点有b个。

    S两步的有x个,T有y个。

    剩下点数fr。

    显然a,b,x,y,fr内部可以随便连边。

    a与x,b与y两两连边。

    fr与x和y连,和a与b其中之一连。

    ansl=a+1LL*a*(a-1)/2+1LL*a*x+1LL*x*(x-1)/2;
    ansr=b+1LL*b*(b-1)/2+1LL*b*y+1LL*y*(y-1)/2;
    ansmid=1LL*x*y+1LL*fr*(fr-1)/2+1LL*fr*(x+y)+1LL*fr*max(a,b);
    ans=ansl+ansr+ansmid-m;

    挣神表示怀疑fr的连边,讲些什么ab还是xy为空的特殊情况。

    然而没有这种数据。

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxn 40005
    using namespace std;
    int n,m,a,b,x,y,S[maxn],T[maxn],X[maxn],Y[maxn];
    long long ansl,ansr,ansmid,ans;
    struct node{
        int u,v;
    }e[1000005];
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&e[i].u,&e[i].v);
            if(e[i].v<e[i].u)swap(e[i].u,e[i].v);
            if(e[i].u==1)S[e[i].v]=1,a++;
            if(e[i].u==2)T[e[i].v]=1,b++;
        }
        for(int i=1;i<=m;i++){
            if(e[i].u==1||e[i].u==2)continue;
            if(S[e[i].u]==1&&S[e[i].v]==1)continue;
            if(T[e[i].u]==1&&T[e[i].v]==1)continue;
            if(S[e[i].u]==1&&!X[e[i].v])X[e[i].v]=1,x++;
            if(S[e[i].v]==1&&!X[e[i].u])X[e[i].u]=1,x++;
            if(T[e[i].u]==1&&!Y[e[i].v])Y[e[i].v]=1,y++;
            if(T[e[i].v]==1&&!Y[e[i].u])Y[e[i].u]=1,y++;
        }
         
        int fr=n-a-b-x-y-2;
        ansl=a+1LL*a*(a-1)/2+1LL*a*x+1LL*x*(x-1)/2;
        ansr=b+1LL*b*(b-1)/2+1LL*b*y+1LL*y*(y-1)/2;
        ansmid=1LL*x*y+1LL*fr*(fr-1)/2+1LL*fr*(x+y)+1LL*fr*max(a,b);
        ans=ansl+ansr+ansmid-m;
        cout<<ans<<endl;
        return 0;
    }
     
  • 相关阅读:
    api封装
    计算字符串内的字出现几次
    Generator 函数的语法
    js原型链的看法
    购物车之上线版思路
    Java并发多线程面试题 Top 50
    Java NIO和IO的区别
    【转载】线程池的原理及实现
    【转载】关于SimpleDateFormat安全的时间格式化线程安全问题
    【转载】Java对象的生命周期
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358849.html
Copyright © 2020-2023  润新知