缩点模板

题目背景

缩点+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<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define M 100010
 5 using namespace std;
 6 int n,m,num,top,ans,cnt,tot;
 7 int head[M],dfn[M],low[M],st[M];
 8 int f[M],sum[M],co[M],val[M],X[M],Y[M];
 9 bool vis[M];
10 struct point{
11     int to,next;
12 }e[M<<1];
13 void add(int from,int to)
14 {
15     e[++num].next=head[from];
16     e[num].to=to;
17     head[from]=num;
18 }
19 void tarjan(int x)
20 {
21     dfn[x]=low[x]=++cnt;
22     st[++top]=x;
23     vis[x]=true;
24     for(int i=head[x];i;i=e[i].next)
25     {
26         int to=e[i].to;
27         if(!dfn[to])
28         {
29             tarjan(to);
30             low[x]=min(low[x],low[to]);
31         }
32         else if(vis[to]) low[x]=min(low[x],dfn[to]);
33     }
34     if(dfn[x]==low[x])
35     {
36         ++tot;
37         vis[x]=false;
38         while(st[top+1]!=x)
39         {
40             co[st[top]]=tot;
41             vis[st[top]]=false;
42             sum[tot]+=val[st[top]];
43             top--;
44         }
45     }
46 }
47 void dfs(int x)
48 {
49     f[x]=sum[x];
50     int maxn=0;
51     for(int i=head[x];i;i=e[i].next)
52     {
53         int to=e[i].to;
54         if(!f[to]) dfs(to);
55         maxn=max(maxn,f[to]);
56     }
57     f[x]+=maxn;
58 }
59 int main()
60 {
61     scanf("%d%d",&n,&m);
62     for(int i=1;i<=n;i++) scanf("%d",&val[i]);
63     for(int i=1;i<=m;i++)
64     {
65         int x,y; scanf("%d%d",&x,&y);
66         X[i]=x; Y[i]=y;
67         add(x,y);
68     }
69     for(int i=1;i<=n;i++)
70         if(!dfn[i])
71             tarjan(i);
72     num=0;
73     memset(e,0,sizeof(e));
74     memset(head,0,sizeof(head));
75     for(int i=1;i<=m;i++)
76         if(co[X[i]]!=co[Y[i]])
77             add(co[X[i]],co[Y[i]]);
78     for(int i=1;i<=tot;i++)
79         if(!f[i])
80         {
81             dfs(i);
82             ans=max(ans,f[i]);
83         }
84     printf("%d",ans);
85     return 0;
86 }

猜你喜欢

转载自www.cnblogs.com/Slrslr/p/9502379.html