题意:
一个人在原点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;
} 
京公网安备 11010502036488号