• P3387 【模板】缩点


    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

    分析

    缩点成有点无环图(树),然后拓扑+dp

    code

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<cstdlib>
      6 
      7 using namespace std;
      8 
      9 const int N = 20100;
     10 const int M = 200100;
     11 struct Edge{
     12     int to,nxt;
     13 }e[M],s[M]; // 不要混用!!!
     14 int head[N],dfn[N],low[N],st[N],bel[N],h[N];
     15 int ru[N],q[1000000],L,R,w[N],sw[N],ans[N];
     16 bool vis[N];
     17 int cnt,tn,tot,top,tot1;
     18 
     19 inline char nc() {
     20     static char buf[100000],*p1 = buf,*p2 = buf;
     21     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF : *p1++;
     22 }
     23 inline int read() {
     24     int x = 0,f = 1;char ch = nc();
     25     for (; ch<'0'||ch>'9'; ch = nc()) 
     26         if (ch=='-') f = -1;
     27     for (; ch>='0'&&ch<='9'; ch = nc()) 
     28         x = x*10+ch-'0';
     29     return x * f;
     30 }
     31 
     32 inline void add_edge(int u,int v) {
     33     e[++tot].to = v,e[tot].nxt = head[u],head[u] = tot;
     34 }
     35 inline void add(int u,int v) {
     36     s[++tot1].to = v,s[tot1].nxt = h[u],h[u] = tot1; // 不要写成e 
     37 }
     38 void tarjan(int u) {
     39     dfn[u] = low[u] = ++tn;
     40     st[++top] = u;
     41     vis[u] = true;
     42     for (int i=head[u]; i; i=e[i].nxt) {
     43         int v = e[i].to;
     44         if (!dfn[v]) {
     45             tarjan(v);
     46             low[u] = min(low[u],low[v]);
     47         }
     48         else if (vis[v]) 
     49             low[u] = min(low[u],dfn[v]);
     50     }
     51     if (low[u]==dfn[u]) {
     52         ++cnt;
     53         do { 
     54             vis[st[top]] = false;
     55             bel[st[top]] = cnt;
     56             sw[cnt] += w[st[top]];
     57             top--;
     58         } while (st[top+1] != u);
     59     }
     60 }
     61 
     62 int main() {
     63 
     64     int n = read(),m = read();
     65     for (int i=1; i<=n; ++i) 
     66         w[i] = read();
     67     for (int i=1; i<=m; ++i) {
     68         add_edge(read(),read());
     69     }
     70     for (int i=1; i<=n; ++i) 
     71         if (!dfn[i]) tarjan(i);
     72     for (int u=1; u<=n; ++u) {
     73         for (int i=head[u]; i; i=e[i].nxt) {
     74             int v = e[i].to;
     75             if (bel[u]!=bel[v]) 
     76                 add(bel[u],bel[v]),ru[bel[v]]++;
     77         }
     78     }
     79     L = 1,R = 0;
     80     for (int i=1; i<=cnt; ++i) {
     81         if (!ru[i]) q[++R] = i,ans[i] = sw[i];
     82     }
     83 
     84     while (L <= R) {
     85         int u = q[L++];
     86         for (int i=h[u]; i; i=s[i].nxt) {
     87             int v = s[i].to;
     88             ans[v] = max(ans[u]+sw[v],ans[v]);
     89             ru[v] --;
     90             if (ru[v]==0) q[++R] = v; // 拓扑!!!不是bfs
     91             
     92         }
     93     }
     94     int mx = 0;
     95     for (int i=1; i<=cnt; ++i) {
     96         mx = max(mx,ans[i]);
     97     }
     98     printf("%d",mx);
     99     return 0;
    100 }
  • 相关阅读:
    Python-05知识-01Python优缺点
    Python-02进阶-06代码优化工具
    Python-02进阶-04多进程多线程
    Python-02进阶-03生成器
    Python-02进阶-02装饰器
    Python-01基础-13功能模块
    Python-01基础-12常用命令
    Python-01基础-11基础知识
    console.dir有很多浏览器,系统的兼容性问题,不要随便用!
    微信支付-签名错误
  • 原文地址:https://www.cnblogs.com/mjtcn/p/7896210.html
Copyright © 2020-2023  润新知