• Codeforces 666B. World Tour 解题报告


    传送门
    题意:一个有N个定点M条边的有向图,dist[i][j]表示从i到j的最短距离,每条边的长度皆为1,请你给出有序的四个点a,b,c,d,使dist[a][b]+dist[b][c]+dist[c][d]最大。


    思路:先用SPFA处理最短路是显然的,然后就是怎么选择点的问题,既然要和最大,那么肯定是两两个点之间的距离最大,那么我们可以预处理出每个点距离最远的点,然后只暴力中间两个点,注意预处理的时候不能用set以求方便,set常数较大会超时,还要注意不能只处理距离最远的,因为会有重复的情况,还要注意重复的情况挪点的时候,要判断size是否大于1,否则会越界。


    AC程序

    //库省略
    using namespace std;
    const int maxn=3005,INF=1e9;
    int n,m;
    vector<int> g[maxn];
    bool vis[maxn];
    int dis[maxn][maxn];
    int far[maxn],len[maxn];
    pii to[maxn][5],back[maxn][5];
    void SPFA()
    {
        for(int i=1;i<=n;i++)
        {
            memset(vis,0,sizeof(vis));
            dis[i][i]=0;
            queue<int> q;
            q.push(i);
            while(!q.empty())
            {
                int u=q.front();
                vis[u]=1;
                q.pop();
                for(int j=0;j<g[u].size();j++)
                {
                    int v=g[u][j];
                    dis[i][v]=min(dis[i][v],dis[i][u]+1);
                    if(!vis[v])
                    q.push(v);
                }
            }
        }
    }
    bool cmp(pii a,pii b)
    {
        return a.fi>b.fi;
    }
    void updateto(int x,int len,int id)
    {
        to[x][3].fi=len;
        to[x][3].se=id;
        sort(to[x],to[x]+4,cmp);
    }
    void updateback(int x,int len,int id)
    {
        back[x][3].fi=len;
        back[x][3].se=id;
        sort(back[x],back[x]+4,cmp);
    }
    int main()
    {
        cin>>n>>m;
        for(int i=0;i<m;i++)
        {
            int x,y;
            cin>>x>>y;
            g[x].pb(y);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                dis[i][j]=INF;
            }
        }
        memset(len,-1,sizeof(len));
        SPFA();
        /*
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                cout<<i<<"to"<<j<<":"<<dis[i][j]<<endl;
            }
        }
        */
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j || dis[i][j]==INF)
                continue;
                updateto(i,dis[i][j],j);
                updateback(j,dis[i][j],i);
            }
        }
        /*
        for(int i=1;i<=n;i++)
        {
            cout<<i<<":";
            for(int j=0;j<3;j++)
            {
                cout<<"(len:"<<back[i][j].fi<<" id:"<<back[i][j].se<<")";
            }
            cout<<endl;
        }
        */
        int maxm=-1;
        int a1=0,a2=0,a3=0,a4=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j || dis[i][j]==INF || !to[j][0].se || !back[i][0].se)
                continue;
                //cout<<i<<" "<<j<<":";
                int ans1,ans2;
                int nex=0,bac=0;
                int nexid=to[j][nex].se,bacid=back[i][bac].se;
                //cout<<bacid<<" "<<i<<" "<<j<<" "<<nexid<<endl;
    
                if(nexid==i)
                nex++;
                if(bacid==j)
                bac++;
                if(!to[j][nex].se || !back[i][bac].se)
                continue;
                nexid=to[j][nex].se;
                bacid=back[i][bac].se;
                int nexlen=to[j][nex].fi,baclen=back[i][bac].fi;
    
                if(nexid==bacid)
                {
                    bac++;nex++;
                    nexid=to[j][nex].se;
                    bacid=back[i][bac].se;
                    if(nexid==0 && bacid==0)
                    continue;
                    if(nexid!=0 && bacid!=0)
                    {
                        bac--;
                        nexlen=to[j][nex].fi;baclen=back[i][bac].fi;
                        ans1=nexlen+baclen;//nex
    
    
                        bac++;nex--;
                        nexlen=to[j][nex].fi;baclen=back[i][bac].fi;
                        ans2=nexlen+baclen;//bac
    
    
                        if(ans1>ans2)
                        bac--,nex++;
                        nexid=to[j][nex].se;
                        bacid=back[i][bac].se;
                    }
                    else
                    {
                        if(nexid==0)
                        nex--;
                        else
                        bac--;
                        nexlen=to[j][nex].fi;baclen=back[i][bac].fi;
                        nexid=to[j][nex].se;bacid=back[i][bac].se;
                        ans2=ans1=nexlen+baclen;
                    }
                }
                ans2=ans1=nexlen+baclen;
                ans1+=dis[i][j];
                ans2+=dis[i][j];
                int ans=max(ans1,ans2);
                //cout<<ans<<endl;
                if(ans>maxm)
                {
                    maxm=ans;
                    a1=bacid;
                    a2=i;
                    a3=j;
                    a4=nexid;
                }
            }
        }
        cout<<a1<<" "<<a2<<" "<<a3<<" "<<a4<<endl;
        return 0;
    }
    
    
  • 相关阅读:
    第三百九十一、二、三、四、五、六、七天 how can I 坚持
    第三百九十天 how can I 坚持
    第三百八十九天 how can I 坚持
    POJ 1745:Divisibility 枚举某一状态的DP
    POJ 1502:MPI Maelstrom Dijkstra模板题
    POJ 1160:Post Office 邮局经典DP
    POJ 1062:昂贵的聘礼
    POJ 1125:Stockbroker Grapevine
    POJ 1236:Network of Schools
    POJ 2186:Popular Cows Tarjan模板题
  • 原文地址:https://www.cnblogs.com/NightRaven/p/9358595.html
Copyright © 2020-2023  润新知