zoukankan      html  css  js  c++  java
  • CDOJ 1431 不是图论 Label:Tarjan || Kosarajn

    Time Limit:1000MS     Memory Limit:65535KB     64bit IO Format:%lld & %llu

    Description

    给出一个nn个点,mm条边的有向图。每个点上有分值,经过这个点时可以获得一定的分数。

    一个点可以经过多次,但是一个点上的分数只能获得一次。

    问最多能获得多少分数,起点任选。

    1<=nn<=30000,1<=mm<=100000

    Input

    输入包含多组数据

    每组数据第一行为nn,mm

    接下来nn行,每行有一个数,表示第ii个节点的分值。

    接下来mm行,每行有两个数aa、bb,表示有一条从aa到bb的有向边

    Output

    每组数据输出一行,每行仅有一个整数:可以获得的最多的分数。

    Sample Input

    5 5 
    1 1 1 2 3 
    1 2 
    2 3 
    3 1 
    1 4 
    1 5 
    5 3 
    1 2 3 4 5 
    1 2 
    1 3 
    4 5

    Sample Output


    9

    代码

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<vector>
     5 #include<cstdio>
     6 #include<queue>
     7 const int MAXN=30010;
     8 using namespace std;
     9 
    10 vector<int> G[MAXN],rG[MAXN],Next[MAXN],vec;
    11 int N,m,f[MAXN],vis[MAXN],ref_nod[MAXN],cost_ref[MAXN],cost_nod[MAXN];
    12 
    13 void init_(){
    14     memset(vis,0,sizeof(vis));
    15     memset(f,0,sizeof(f));
    16     memset(ref_nod,0,sizeof(ref_nod));
    17     memset(cost_ref,0,sizeof(cost_ref));
    18     memset(cost_nod,0,sizeof(cost_nod));
    19     for(int i=0;i<=N;i++){
    20         G[i].clear();
    21         rG[i].clear();
    22         Next[i].clear();
    23         vec.clear();
    24     }
    25 }
    26 
    27 void rdfs(int x,int k){
    28     vis[x]=1;
    29     ref_nod[x]=k;
    30     cost_ref[k]+=cost_nod[x];
    31     for(int i=0;i<rG[x].size();i++){
    32         int to=rG[x][i];
    33         if(!vis[to]) rdfs(to,k);
    34         if(ref_nod[to]!=k) Next[k].push_back(ref_nod[to]);
    35     }
    36 }
    37 
    38 void dfs(int x){
    39     vis[x]=1;
    40     for(int i=0;i<G[x].size();i++){
    41         int to=G[x][i];
    42         if(!vis[to]) dfs(to);
    43     }
    44     vec.push_back(x);
    45 }
    46 
    47 int Sum(int x){
    48     vis[x]=1;
    49     if(f[x]>0) return f[x];
    50     int tmp=0;
    51     for(int i=0;i<Next[x].size();i++){
    52         tmp=max(tmp,Sum(Next[x][i]));
    53     }
    54     return f[x]=tmp+cost_ref[x];
    55 }
    56 
    57 void scc(){
    58     int k=1;
    59     memset(vis,0,sizeof(vis));
    60     for(int i=1;i<=N;i++)
    61         if(!vis[i]) dfs(i);
    62     /**/
    63     memset(vis,0,sizeof(vis));
    64     for(int i=vec.size()-1;i>=0;i--)
    65         if(!vis[vec[i]]) rdfs(vec[i],k++);
    66     
    67     int tot=0;
    68     memset(vis,0,sizeof(vis));
    69     for(int i=1;i<k;i++){
    70         if(!vis[i]) tot=max(tot,Sum(i));
    71     }
    72     printf("%d
    ",tot);
    73 }
    74 
    75 int main(){
    76 //    freopen("01.in","r",stdin);
    77     while(scanf("%d%d",&N,&m)==2){
    78         init_();
    79         for(int i=1;i<=N;i++) scanf("%d",&cost_nod[i]);
    80         for(int i=1;i<=m;i++){
    81             int x,y;
    82             scanf("%d%d",&x,&y);
    83             G[x].push_back(y);
    84             rG[y].push_back(x);
    85         }
    86         scc();
    87     }
    88     return 0;
    89 }

    三个类似dfs的玩意儿,记得初始化~

    Next记录该强联通的下一个强联通

    ref就是各种映射

    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!
  • 相关阅读:
    Solr的配置和在java中的使用
    druid + mysql + mybatis 批量更新报错
    linux find命令-print0和xargs中-0使用技巧
    Shell 函数相关
    公钥、私钥和数字签名这样最好理解
    Liunx find/locate/whereis/which 总结
    Linux find命令
    Shell bash 数学运算 bc
    Shell 使用 expr 进行数学运算
    Shell 有类型变量
  • 原文地址:https://www.cnblogs.com/radiumlrb/p/5928995.html
Copyright © 2011-2022 走看看