强连通分量题。题意:圣诞老人准备在圣诞节给ACMer送礼物,每个ACMer都有一个寝室,寝室之间有单向道路。每个人对于圣诞老人发的礼物都有一个心情值的影响,正数表示好的影响,负数则是不好的影响。圣诞老人每到达一个寝室可以选择进去发礼物也可以选择不发,并且圣诞老人可以到达一个寝室多次但是不能给一个寝室发多个礼物。现在给你寝室之间的道路图,请你选择一条路径使得圣诞老人可以造成最大的心情影响值,输出这个值。
我的解题思路:因为圣诞老人可以选择不发礼物,所以负数的心情影响可以改成0。首先用Tarjan跑一遍强连通并记录好每一个强连通分量的心情值,然后重新建强连通分量图,找到每一个入度为0的强连通分量跑一次dfs找出心情值最大的路径然后输出心情值就ok了。
我的解题代码:强连通分量Tarjan算法+缩点
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 30001;
vector <int> e[N];
vector <int> scce[N]; //强连通分量图
int dfn[N], low[N];
int belong[N];
int vis[N];
int stack[N], stop;
int timer;
int sccn;
int indeg[N];
int comf[N]; //点心情值
int scccomf[N]; //强连通分量心情值
int ans;
int n, m;
void InitRead();
void DataProcess();
void Tarjan(int x);
void Dfs(int x, int ci);
int main()
{
while (~scanf("%d %d", &n, &m))
{
InitRead();
DataProcess();
}
return 0;
}
void InitRead()
{
memset(vis, 0, sizeof(vis));
memset(indeg, 0, sizeof(indeg));
ans = sccn = timer = stop = 0;
for (int i=0; i<n; ++i)
{
scanf("%d", &comf[i]);
comf[i] = comf[i] < 0 ? 0 : comf[i];
e[i].clear();
scce[i].clear();
}
int a, b;
for (int i=0; i<m; ++i)
{
scanf("%d %d", &a, &b);
e[a].push_back(b);
}
return;
}
void DataProcess()
{
for (int i=0; i<n; ++i)
{
if (!vis[i])
{
Tarjan(i);
}
}
for (int i=0; i<n; ++i) //重建强连通分量图并计算强连通分量入度
{
int size = e[i].size();
for (int j=0; j<size; ++j)
{
if (belong[i] != belong[e[i][j]])
{
scce[belong[i]].push_back(belong[e[i][j]]);
indeg[belong[e[i][j]]]++;
}
}
}
for (int i=1; i<=sccn; ++i)
{
if (indeg[i] == 0)
{
Dfs(i, scccomf[i]);
}
}
printf("%d\n", ans);
return;
}
void Tarjan(int x)
{
int y;
dfn[x] = low[x] = ++timer;
stack[stop++] = x;
vis[x] = 2;
int size = e[x].size();
for (int i=0; i<size; ++i)
{
y = e[x][i];
if (!vis[y])
{
Tarjan(y);
low[x] = min(low[x], low[y]);
}
else if (vis[y] == 2)
{
low[x] = min(low[x], dfn[y]);
}
}
if (dfn[x] == low[x])
{
sccn++;
int temp = 0;
do
{
y = stack[--stop];
vis[y] = 1;
belong[y] = sccn;
temp += comf[y];
} while (x != y);
scccomf[sccn] = temp;
}
return;
}
void Dfs(int x, int ci)
{
int size = scce[x].size();
if (size == 0)
{
ans = max(ans, ci);
return;
}
for (int i=0; i<size; ++i)
{
Dfs(scce[x][i], ci + scccomf[scce[x][i]]);
}
return;
}