• hihoCoder #1185 : 连通性·三(强联通分量+拓扑排序)


    #1185 : 连通性·三

    时间限制:10000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家。今天一大早,约翰因为有事要出去,就拜托小Hi和小Ho忙帮放牧。

    约翰家一共有N个草场,每个草场有容量为W[i]的牧草,N个草场之间有M条单向的路径。

    小Hi和小Ho需要将牛羊群赶到草场上,当他们吃完一个草场牧草后,继续前往其他草场。当没有可以到达的草场或是能够到达的草场都已经被吃光了之后,小hi和小Ho就把牛羊群赶回家。

    一开始小Hi和小Ho在1号草场,在回家之前,牛羊群最多能吃掉多少牧草?

    举个例子:

    图中每个点表示一个草场,上部分数字表示编号,下部分表示草场的牧草数量w。

    在1吃完草之后,小Hi和小Ho可以选择把牛羊群赶到2或者3,假设小Hi和小Ho把牛羊群赶到2:

    吃完草场2之后,只能到草场4,当4吃完后没有可以到达的草场,所以小Hi和小Ho就把牛羊群赶回家。

    若选择从1到3,则可以到达5,6:

    选择5的话,吃完之后只能直接回家。若选择6,还可以再通过6回到3,再到5。

    所以该图可以选择的路线有3条:

    1->2->4 		total: 11
    1->3->5 		total: 9
    1->3->6->3->5: 		total: 13
      

    所以最多能够吃到的牧草数量为13。

    本题改编自USACO月赛金组

    提示:强连通分量

    输入

    第1行:2个正整数,N,M。表示点的数量N,边的数量M。1≤N≤20,000, 1≤M≤100,000

    第2行:N个正整数,第i个整数表示第i个牧场的草量w[i]。1≤w[i]≤100,000

    第3..M+2行:2个正整数,u,v。表示存在一条从u到v的单向路径。1≤u,v≤N

    输出

    第1行:1个整数,最多能够吃到的牧草数量。

    代码

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<vector>
     5 #include<stack>
     6 #include<queue>
     7 #include<algorithm>
     8 using namespace std;
     9 const int N=2e4+5;
    10 
    11 vector<int>v[N];
    12 vector<int>gra[N];
    13 stack<int>sk;
    14 int n,m,cnt,num,ans;
    15 int val[N],low[N],dfn[N],fa[N],sum[N],indeg[N],dp[N];
    16 bool vis[N];
    17 
    18 //求出强连通分量
    19 void tarjan(int u){
    20     low[u]=dfn[u]=++cnt;
    21     sk.push(u);
    22     for(int i=0;i<v[u].size();i++){
    23         int t=v[u][i];
    24         if(!dfn[t]){
    25             tarjan(t);
    26             low[u]=min(low[u],low[t]);
    27         }
    28         else if(!fa[t]) low[u]=min(low[u],dfn[t]);
    29     }
    30     if(low[u]==dfn[u]){
    31         num++;
    32         while(!sk.empty()){
    33             int t=sk.top();
    34             sk.pop();
    35             fa[t]=num;
    36             sum[num]+=val[t];
    37             if(t==u) break;
    38         }
    39     }
    40 }
    41 
    42 //拓扑排序求最大价值
    43 int topo(){
    44     queue<int>q;
    45     for(int i=1;i<=num;i++){
    46         if(indeg[i]==0)
    47             q.push(i);
    48     }
    49     int ans=0;
    50     while(!q.empty()){
    51         int k=q.front();
    52         q.pop();
    53         dp[k]+=sum[k];
    54         ans=max(dp[k],ans);
    55         for(int i=0;i<gra[k].size();i++){
    56             int t=gra[k][i];
    57             indeg[t]--;
    58             dp[t]=max(dp[t],dp[k]);
    59             if(indeg[t]==0)
    60                 q.push(t);
    61         }
    62     }
    63     return ans;
    64 }
    65 
    66 int main(){
    67     scanf("%d%d",&n,&m);
    68     for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    69     for(int i=1;i<=m;i++){
    70         int a,b;
    71         scanf("%d%d",&a,&b);
    72         v[a].push_back(b);
    73     }
    74     tarjan(1);                  //起点是1
    75     //建新图
    76     for(int i=1;i<=n;i++){
    77         if(fa[i]==0) continue;
    78         for(int j=0;j<v[i].size();j++){
    79             int t=v[i][j];
    80             if(fa[i]!=fa[t])
    81                 gra[fa[i]].push_back(fa[t]);
    82         }
    83     }
    84     //计算入度
    85     for(int i=1;i<=num;i++){
    86         for(int j=0;j<gra[i].size();j++){
    87             int t=gra[i][j];
    88             indeg[t]++;
    89         }
    90     }
    91     //利用拓扑排序算出答案
    92     printf("%d
    ",topo());
    93     return 0;
    94 }
  • 相关阅读:
    echarts 点击事件 点击一次触发多次
    echarts 没有数据时,无数据展示
    递归 出现的一些问题
    echarts 下钻 返回设成按钮的样式
    阻止冒泡 阻止默认事件
    前端如何绘制svg格式图片
    html头部的标签有哪些?
    ant design 封装可填写Tag标签的input框
    React:通过Vite集成Tailwind CSS
    React:通过vite批量导入图片
  • 原文地址:https://www.cnblogs.com/fu3638/p/8635548.html
Copyright © 2020-2023  润新知