• P3387 【模板】缩点


    题目背景

    缩点+DP

    题目描述

    给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。

    允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。

    输入输出格式

    输入格式:

    第一行,n,m

    第二行,n个整数,依次代表点权

    第三至m+2行,每行两个整数u,v,表示u->v有一条有向边

    输出格式:

    共一行,最大的点权之和。

    输入输出样例

    输入样例#1: 复制
    2 2
    1 1
    1 2
    2 1
    输出样例#1: 复制
    2

    说明

    n<=10^4,m<=10^5,点权<=1000

    算法:Tarjan缩点+DAGdp

    题解:缩点+记忆化搜索

      1 #include<cstdio>
      2 #include <algorithm>
      3 #include <stack>
      4 #include <vector>
      5 #include <cstring>
      6 using namespace std;
      7 
      8 const int MAXN=1e5+10;
      9 const int inf=0x3f3f3f3f;
     10 struct node{
     11     int to;
     12     int next;
     13 }edge[MAXN*4];
     14 int head[MAXN];
     15 int val[MAXN];
     16 bool instack[MAXN];
     17 int cnt;
     18 int dfn[MAXN],low[MAXN];
     19 int sum[MAXN];
     20 void add(int x,int y)
     21 {
     22     edge[++cnt].to =y;
     23     edge[cnt].next=head[x];
     24     head[x]=cnt;
     25 }
     26 int Time,num;
     27 stack<int >st;
     28 vector<int >G[MAXN];
     29 int du[MAXN];
     30 int color[MAXN];
     31 int x[MAXN],y[MAXN];
     32 int f[MAXN];
     33 void search(int x)
     34 {
     35     if(f[x]) return;
     36     f[x]=sum[x];
     37     int maxsum=0;
     38     for (int i = 0; i <G[x].size() ; ++i) {
     39         if(!f[G[x][i]]) search(G[x][i]);
     40         maxsum=max(maxsum,f[G[x][i]]);
     41     }
     42     f[x]+=maxsum;
     43 
     44 }
     45 void tarjan(int u)
     46 {
     47     dfn[u]=low[u]= ++Time;
     48     st.push(u);
     49     instack[u]=true;
     50     for (int i = head[u]; i !=-1 ; i=edge[i].next) {
     51         int v=edge[i].to;
     52         if(!dfn[v]){
     53             tarjan(v);
     54             low[u]=min(low[u],low[v]);
     55         }
     56         else if(instack[v]) low[u]=min(low[u],dfn[v]);
     57     }
     58     if(dfn[u]==low[u])
     59     {
     60         int x;
     61         num++;
     62         while(1) {
     63             x=st.top();
     64             st.pop();
     65             color[x]=num;
     66             instack[x]=false;
     67             if(x==u) break;
     68         }
     69 
     70     }
     71 }
     72 
     73 int main()
     74 {
     75     int n,m;
     76     scanf("%d%d",&n,&m);
     77     for (int i = 1; i <=n ; ++i) {
     78         scanf("%d",&val[i]);
     79     }
     80     cnt=0;
     81     memset(head,-1,sizeof(head));
     82     memset(instack,false, sizeof(instack));
     83     memset(sum, 0,sizeof(sum));
     84     for (int i = 1; i <=m ; ++i) {
     85         scanf("%d%d",&x[i],&y[i]);
     86         add(x[i],y[i]);
     87     }
     88     for (int i = 1; i <=n ; ++i) {
     89         if(!dfn[i]) tarjan(i);
     90     }
     91     for (int i = 1; i <=n ; ++i) {
     92         sum[color[i]]+=val[i];
     93     }
     94     for (int k = 1; k <=num ; ++k) {
     95 //        printf("%d --%d
    ",k,sum[k]);
     96     }
     97     for (int i = 1; i <=m ; ++i) {
     98         if(color[x[i]]!=color[y[i]])
     99         {
    100             G[color[x[i]]].push_back(color[y[i]]);
    101         }
    102     }
    103     for (int i = 1; i <=num; ++i) {
    104         for (int j = 0; j <G[i].size() ; ++j) {
    105 //            printf("%d-->%d
    ",i,G[i][j]);
    106         }
    107     }
    108 
    109     int ans=0;
    110     for (int i = 1; i <=num ; ++i) {
    111         if(!f[i]){
    112             search(i);
    113             ans=max(ans,f[i]);
    114         }
    115     }
    116     printf("%d
    ",ans);
    117     return 0;
    118 }
  • 相关阅读:
    金山词霸注册表怎么删
    新手学习jquery
    《企业应用架构模式》(POEAA)读书笔记
    Silverlight 4 tools
    asp.net非常基础的面试题
    VS 2010 中文版正式版无法安装Silverlight4 Tools的解决办法
    OnPreRender(EventArgs e) 事件常用的方法
    各大搜索引擎网站登录入口
    向用户控件传递参数的问题
    URLRewriter
  • 原文地址:https://www.cnblogs.com/-xiangyang/p/9337196.html
Copyright © 2020-2023  润新知