zoukankan      html  css  js  c++  java
  • Codeforces 1016F Road Projects

    正解思路,感觉应该是先判特殊情况,比如新建的路线可以建在于1-n无关的地方,具体判别方法见代码

    然后再判断旧路线两端的最大贡献值,即代码中的ans,枚举1-n线路中的每个节点i,求1-[1,i]节点的最大值和[i+1,n]-n节点的最大值,维护ans即可

    #include<iostream>
    #include<cstdio> 
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<string.h>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<fstream>
    #include<cstdlib>
    #include<ctime>
    #include<list>
    #include<climits>
    using namespace std;
    #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    #define fopen freopen("input.txt", "r", stdin);freopen("output.txt", "w", stdout);
    #define scd(a) scanf("%d",&a)
    #define scf(a) scanf("%lf",&a)
    #define scl(a) scanf("%lld",&a)
    #define sci(a) scanf("%I64d",&a)
    #define scs(a) scanf("%s",a)
    #define left asfdasdasdfasdfasfasdfasfsdfasfdas
    typedef long long ll;
    const int desll[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    const ll mod=1e9+7;
    const int maxn=3e5+7;
    const int maxm=1e8+7;
    const double eps=1e-4;
    int m,n;
    int ar[maxn];
    set<pair<ll,int> > se1,se2;
    pair<int,pair<ll,int> > pal1[maxn],pal2[maxn];
    int le1,le2;
    vector<pair<int,int> > e[maxn];
    int markl[maxn],mark;
    set<pair<int,int> > seMa;
    ll ans=0,ansMid;
    int ansl[maxn];
    void dfs(int u,int pre)
    {
        if(u==n){
            mark=1;
            markl[u]=1;
            return ;
        }
        for(int i=0;i<e[u].size();i++){
            int v=e[u][i].first;
            if(v==pre)continue;
            dfs(v,u);
            if(mark){
                markl[u]=1;
                return ;
            }
        }
    }
    void dfs1(int u,int pre,ll sum,int ins)
    {
        pal1[le1].first=ins;
        pal1[le1].second.first=sum;
        pal1[le1++].second.second=u;
        if(u==n){
            ansMid=sum;
        }
        for(int i=0;i<e[u].size();i++){
            int v=e[u][i].first;
            if(v==pre)continue;
            dfs1(v,u,sum+e[u][i].second,ins+markl[v]);
        }
    }
    void dfs2(int u,int pre,ll sum,int ins)
    {
        pal2[le2].first=ins;
        pal2[le2].second.first=sum;
        pal2[le2++].second.second=u;
        for(int i=0;i<e[u].size();i++){
            int v=e[u][i].first;
            if(v==pre)continue;
            dfs2(v,u,sum+e[u][i].second,ins+markl[v]);
        }
    }
    int main()
    {
        scd(n);
        scd(m);
        for(int i=1;i<n;i++){
            int a,b,c;
            scd(a);scd(b);scd(c);
            e[a].push_back(make_pair(b,c));
            e[b].push_back(make_pair(a,c));
            seMa.insert(make_pair(a,b));
            seMa.insert(make_pair(b,a));
        }
        memset(markl,0,sizeof(markl));
        mark=0;
        le1 = le2 = 0;
        ans=0,ansMid=0;
        dfs(1,0);//求1-n所经过的各个节点
        dfs1(1,0,0,0);
        dfs2(n,0,0,0);
        sort(pal1,pal1+le1);
        sort(pal2,pal2+le2);
        for(int i=1;i<=n;i++){//看新建线路能否建在与1-n无关的地方,若能,其实后面的while维护ans可省略
            int ins=0;
            if(markl[i]){
                for(int j=0;j<e[i].size();j++){
                    int x=e[i][j].first;
                    if(markl[x]==0)ins++;
                }
            }
            else{
                ins=e[i].size();
            }
            if(ins>=2){
                ans=ansMid;
                break;
            }
        }
    
        int maxNum=pal1[le1-1].first;
        int be=0;
        for(int i=0;i<le2;i++){
            if(pal2[i].first==maxNum)break;
            se2.insert(pal2[i].second);
            be=i;
        }
        int ins=0,res=0;
        while(res<maxNum){//维护ans
            while(pal1[ins].first<=res){
                se1.insert(pal1[ins].second);
                ins++;
            }
            auto au1=se1.end();
            auto au2=se2.end();
            au1--;
            au2--;
            if(seMa.count(make_pair(au1->second,au2->second))){//若两个节点本身相连,即都在1-n的主线路上,则需退一步判次大值
                if(au1!=se1.begin()){
                    au1--;
                    ans = max(ans, au1->first+au2->first);
                    au1++;
                }
                if(au2!=se2.begin()){
                    au2--;
                    ans = max(ans, au1->first+au2->first);
                    au2++;
                }
            }
            else ans = max(ans, au1->first+au2->first);
            res++;
            while(pal2[be].first+res==maxNum){
                se2.erase(pal2[be].second);
                be--;
            }
        }
        //cout<<maxNum<<" "<<ansMid<<" "<<ans<<endl;
        for(int i=0;i<m;i++){
            int ins;
            scd(ins);
            printf("%I64d
    ",min(ansMid,ans+ins));
        }
        return 0;
    }
  • 相关阅读:
    postman 安装,配置,鉴权
    monkey操作,获取包名,参数,日志,百分比
    monkey环境搭建
    postman接口测试&压力测试
    Fiddler介绍(PC端+Android,IOS端,弱网)
    软件测试的环境搭建
    python2.x- selenium-robot framework自动化测试环境搭建
    SVN的简单操作,版本控制
    svn介绍和安装
    js 函数和函数的参数
  • 原文地址:https://www.cnblogs.com/wa007/p/9445025.html
Copyright © 2011-2022 走看看