题意:
一个人在原点s,每个城市有对应的评价值w,不能走上次刚走的点,
比如最开始从6-2,下一次不能立即从2-6,但可以通过绕一圈6-2-1-3-4-2-6的方式回到6,意味着每个节点每条边都有可能经过多次,每个节点只算第一次经过时候的值。
求他在整个图中经过的城市累积的评价值的最大值。
既然可以转圈圈,首先对强连通分量缩点,
缩完点之后第一次dfs预处理每个点的val值,对每个点,只要他的后代结点有环,就可以到达后代结点并回来,
那么后代结点的值直接累加到该点,对后代节点置零。
第二次dfs就是普通树上dp,因为到现在就是选择哪条链的问题。
还有模一下tarjan,一次dfs又能求lca又能求强连通分量%%%%%
用tarjan求强连通分量之后编个号就好了,,意外的好操作呢。。
#include <bits/stdc++.h> using namespace std; #define endll '\n' #define C getchar() typedef __int64 lll; typedef long long ll; #define pi acos(-1.0) #define INF 0x3f3f3f3f #define mod 1000000007 #define pii pair<int, int> const int MAXN = 1e6 + 10; #define stop system("pause") #define lowbit(x) ((x) & (-x)) #define Temp template <typename T> #define mem(a, b) memset(a, b, sizeof(a)) #define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) Temp inline void rd(T &s) { s = 0;T t = 1, k = C; for (; k < '0' || k > '9'; k = C)if (k == '-') t = -1; for (; k >= '0' && k <= '9'; k = C) s = (s << 1) + (s << 3) + (k ^ 48); s *= t; } // int n,m,s; int w[MAXN]; vector<int>mp[MAXN],vc[MAXN]; //trajan int tot; int id[MAXN]; int top,sta[MAXN],ins[MAXN];//模拟栈 int cnt,dfn[MAXN],low[MAXN];//结点编号及该点所在的强连通分量最小编号 //dfs int sz[MAXN];//该点为多个点缩成 ll dp[MAXN],val[MAXN]; void tra(int x,int fa) { low[x]=dfn[x]=++cnt;// sta[++top]=x;ins[x]=1; for(int i=0;i<mp[x].size();++i) { int v=mp[x][i]; if(v==fa) continue; if(!dfn[v]) tra(v,x),low[x]=min(low[x],low[v]); else if(ins[v]) low[x]=min(low[x],dfn[v]); } if(low[x]==dfn[x]) { tot++;//新图对应编号 while(1) { int j=sta[top--]; id[j]=tot; ins[j]=0; sz[tot]++; val[tot]+=w[j]; ins[j]=0; if(j==x) break; } } } void dfs1(int u,int fa)//如果一个点的儿子结点有环,那么可以可以走到并且可以回来 { for(int i=0;i<vc[u].size();++i) { int v=vc[u][i]; if(v==fa) continue; dfs1(v,u); if(sz[v]>1) { val[u]+=val[v]; sz[u]+=sz[v]; val[v]=0; } } } void dfs(int u,int fa) { for(int i=0;i<vc[u].size();++i) { int v=vc[u][i]; if(v==fa) continue; dfs(v,u); dp[u]=max(dp[u],dp[v]); } dp[u]+=val[u]; } int main() { rd(n),rd(m); for(int i=1;i<=n;++i) rd(w[i]); for(int i=0;i<m;++i) { int u,v;rd(u),rd(v); mp[u].push_back(v),mp[v].push_back(u); } rd(s); //缩点 cnt=tot=top=0; tra(1,0); for(int u=1;u<=n;u++)//建新图 { for(int i=0;i<mp[u].size();++i) { int v=mp[u][i]; if(id[v] == id[u]) continue; vc[id[u]].push_back(id[v]); } } // dfs1(id[s],-1); dfs(id[s],-1); printf("%lld\n",dp[id[s]]); //stop; return 0; }