• 洛谷P4742(tarjan缩点+拓扑DP)


    https://www.luogu.org/problemnew/show/P4742

    题目背景

    [Night - 20:02[Night20:0P.M.]P.M.]

    夜空真美啊……但是……快要结束了呢……

    题目描述

    一天的活动过后,所有学生都停下来欣赏夜空下点亮的风筝。CurtisCurtiNishikinoNishikino想要以更近的视角感受一下,所以她跑到空中的风筝上去了(这对于一个妹子来说有点匪夷所思)! 每只风筝上的灯光都有一个亮度 k_iki. 由于风的作用,一些风筝缠在了一起。但是这并不会破坏美妙的气氛,缠在一起的风筝会将灯光汇聚起来,形成更亮的光源!

    CurtisCurtiNishikinoNishikino已经知道了一些风筝间的关系,比如给出一对风筝(a,b)(a,b), 这意味着她可以从 aa 跑到 bb上去,但是不能返回。

    现在,请帮她找到一条路径(她可以到达一只风筝多次,但只在第一次到达时她会去感受上面的灯光), 使得她可以感受到最多的光亮。同时请告诉她这条路径上单只风筝的最大亮度,如果有多条符合条件的路径,输出能产生最大单只风筝亮度的答案。

    输入输出格式

    输入格式:

    第一行两个整数 nn 和 mm. nn 是风筝的数量, mm 是风筝间关系对的数量.

    接下来一行 nn 个整数 k_iki.

    接下来 mm 行, 每行两个整数 aa 和 bb, 即CurtisCurtis可以从 aa 跑到 bb.

    输出格式:

    一行两个整数。CurtisCurtis在计算出的路径上感受到的亮度和,这条路径上的单只风筝最大亮度.

    输入输出样例

    输入样例#1: 复制
    5 5
    8 9 11 6 7
    1 2
    2 3
    2 4
    4 5
    5 2
    输出样例#1: 复制
    41 11

    说明

    对于 20\%20% 的数据, 0<n le 5 imes10^3, 0 < m le 10^40<n5×103, 0<m104.

    对于 80\%80% 的数据, 0 < n le 10^5, 0 < m le 3 imes10^50<n105, 0<m3×105.

    对于 100\%100% 的数据, 0<nle2 imes10^5, 0<mle5 imes10^5, 0<kle2000<n2×105, 0<m5×105, 0<k200.

    思路:tarjan缩点+拓扑DP,其实DP就是最短路松弛操作。

    ///缩点+拓扑DP
    #include<bits/stdc++.h>
    #define INF 0x3f3f3f3f
    using namespace std;
    const int maxn = 2e5+4;
    int n,m,cnt,color;
    int a[maxn],DFN[maxn],LOW[maxn],belong[maxn],dis[maxn],maxdis[maxn],maxval[maxn],in[maxn],sumval[maxn];
    bool vis[maxn];
    stack<int>s;
    vector <int> G[maxn],NG[maxn];
    void tarjan(int x){
        DFN[x]=LOW[x]=++cnt;
        vis[x]=true;
        s.push(x);
        for(int i=0;i<G[x].size();i++){
            int to=G[x][i];
            if(!DFN[to]){
                tarjan(to);
                LOW[x]=min(LOW[x],LOW[to]);
            }else if(vis[to]){
                LOW[x]=min(LOW[x],DFN[to]);
            }
        }
        if(LOW[x]==DFN[x]){
            int temp;
            color++;
            maxval[color]=0;
            do{
                temp=s.top();
                s.pop();
                vis[temp]=false;
                belong[temp]=color;
                sumval[color]+=a[temp];
                maxval[color]=max(maxval[color],a[temp]);
            }while(temp!=x);
        }
    }
    ///dis[x]/以x为终点的最大距离和,maxdis[x]/以x为终点的最大距离间隔
    void tpu(){
        fill(dis,dis+color+1,-INF);
        queue<int>Q;
        for(int i=1;i<=color;i++){
            if(in[i]==0){
                dis[i]=sumval[i];
                maxdis[i]=maxval[i];
                Q.push(i);
            }
        }
        while(!Q.empty()){
            int u=Q.front();
            Q.pop();
            for(int i=0;i<NG[u].size();i++){
                int to=NG[u][i];
                in[to]--;
                if(dis[to]<dis[u]+sumval[to]){///如果从u-》to的价值和更加大,就更新,而且要更新maxdis,为maxval[to]和之前dis[u]的更大的那个
                    dis[to]=dis[u]+sumval[to];
                    maxdis[to]=max(maxdis[u],maxval[to]);
                }else if(dis[to]==dis[u]+sumval[to]){///如果相等,就要考虑maxdis的更新
                    maxdis[to]=max(maxdis[to],maxdis[u]);
                }
                if(in[to]==0){
                    Q.push(to);
                }
            }
        }
        int anssum=0,ansmax=0;
        for(int i=1;i<=color;i++){
            if(anssum<dis[i]){
                anssum=dis[i];
                ansmax=maxdis[i];
            }else if(anssum==dis[i]){
                ansmax=max(ansmax,maxdis[i]);
            }
        }
        printf("%d %d
    ",anssum,ansmax);
    }
    int main(){
        int x,y;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        for(int i=0;i<m;i++){
            scanf("%d%d",&x,&y);
            G[x].push_back(y);
        }
        for(int i=1;i<=n;i++){
            if(!DFN[i]){
                tarjan(i);
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=0;j<G[i].size();j++){
                int to=G[i][j];
                if(belong[i]!=belong[to]){
                    NG[belong[i]].push_back(belong[to]);
                    in[belong[to]]++;
                }
            }
        }
        tpu();
        return 0;
    }
  • 相关阅读:
    寒假生活
    VS2010调试时修改代码 调试时源文件与模块生成时的文件不同
    如何在VS VC 中DLL使用CString类
    SVChost执行原理学习
    error LNK2001: unresolved external symbol __imp__PathFileExistsA@4
    visual studio 2010 遇到了异常,可能是由某个扩展导致的...
    C++运算各版本学习
    寒江独钓-键盘过滤学习2修改IDT + IOAPIC重定位表截获PS2键盘中断
    寒江独钓-键盘过滤学习1传统型的键盘过滤
    ObReferenceObjectByName 函数解析
  • 原文地址:https://www.cnblogs.com/liuzuolin/p/10845759.html
Copyright © 2020-2023  润新知