• poj3160 强连通+记忆化搜索


    题意:有一张 n 点 m 边的有向无环图,每个点有各自的权值,可正可负,现在从一个点开始走,一直走到不能走到其他点为止,每经过一个点,可以选择获得或不获得它的权值,每个点可以走多次,但是权值只能获得一次,问最后最多能够获得多少权值。

    每个点可以走多次,权值只能获得一次,路过的时候权值可以不获得,所以我们只需要考虑正的权值就行了。在一个强连通分量中的点的权值我们都能获得,所以先缩点,得到一个有向无环图,然后从每个入度为 0 的点开始DFS,累计得到的最大权值就行。

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<stack>
      4 #include<queue>
      5 using namespace std;
      6 
      7 const int maxn=3e4+5;
      8 const int maxm=2e5+5;
      9 
     10 int head[2][maxn],point[2][maxm],nxt[2][maxm],size[2];
     11 int n,t,scccnt;
     12 int stx[maxn],low[maxn],scc[maxn],num[maxn],id[maxn],v[maxn];
     13 int dp[maxn];
     14 stack<int>S;
     15 
     16 int max(int a,int b){return a>b?a:b;}
     17 
     18 void init(){
     19     memset(head,-1,sizeof(head));
     20     size[0]=size[1]=0;
     21     memset(num,0,sizeof(num));
     22     memset(id,0,sizeof(id));
     23     memset(dp,-1,sizeof(dp));
     24 }
     25 
     26 void add(int a,int b,int c=0){
     27     point[c][size[c]]=b;
     28     nxt[c][size[c]]=head[c][a];
     29     head[c][a]=size[c]++;
     30 }
     31 
     32 void dfs(int s){
     33     stx[s]=low[s]=++t;
     34     S.push(s);
     35     for(int i=head[0][s];~i;i=nxt[0][i]){
     36         int j=point[0][i];
     37         if(!stx[j]){
     38             dfs(j);
     39             low[s]=min(low[s],low[j]);
     40         }
     41         else if(!scc[j]){
     42             low[s]=min(low[s],stx[j]);
     43         }
     44     }
     45     if(low[s]==stx[s]){
     46         scccnt++;
     47         while(1){
     48             int u=S.top();S.pop();
     49             scc[u]=scccnt;
     50             num[scccnt]+=v[u]>0?v[u]:0;
     51             if(s==u)break;
     52         }
     53     }
     54 }
     55 
     56 void setscc(){
     57     memset(stx,0,sizeof(stx));
     58     memset(scc,0,sizeof(scc));
     59     t=scccnt=0;
     60     for(int i=1;i<=n;++i)if(!stx[i])dfs(i);
     61     for(int i=1;i<=n;++i){
     62         for(int j=head[0][i];~j;j=nxt[0][j]){
     63             int k=point[0][j];
     64             if(scc[i]!=scc[k]){
     65                 add(scc[i],scc[k],1);
     66                 id[scc[k]]++;
     67             }
     68         }
     69     }
     70 }
     71 
     72 int dfs1(int s){
     73     if(~dp[s])return dp[s];
     74     int maxx=0;
     75     for(int i=head[1][s];~i;i=nxt[1][i]){
     76         int j=point[1][i];
     77         maxx=max(maxx,dfs1(j));
     78     }
     79     dp[s]=maxx+num[s];
     80     return dp[s];
     81 }
     82 
     83 int main(){
     84     int m;
     85     while(scanf("%d%d",&n,&m)!=EOF){
     86         init();
     87         for(int i=1;i<=n;++i)scanf("%d",&v[i]);
     88         while(m--){
     89             int a,b;
     90             scanf("%d%d",&a,&b);
     91             a++;
     92             b++;
     93             add(a,b);
     94         }
     95         setscc();
     96         int ans=0;
     97         for(int i=1;i<=scccnt;++i){
     98             if(!id[i])ans=max(ans,dfs1(i));
     99         }
    100         printf("%d
    ",ans);
    101     }
    102     return 0;
    103 }
    View Code
  • 相关阅读:
    Vue项目端口号占用
    理解vuex -- vue的状态管理模式
    2018-7-10杂记
    JS 数组操作总结
    JS 字符串操作总结
    【javascript练习题】函数
    【javascript练习题】this指针和作用域
    canal实时同步mysql binlog到rabbitmq
    Hexo+GitHub+Netlify一站式搭建属于自己的博客网站
    Git学习原版手稿
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4817128.html
Copyright © 2020-2023  润新知