您的位置:首页 > 其它

poj 3160 (强连通缩点&简单dp)

2017-09-02 09:48 399 查看
Flymouse从武汉大学ACM集训队退役后,做起了志愿者,在圣诞节来临时,Flymouse要打扮成圣诞老人给集训队员发放礼物。集训队员住在校园宿舍的不同寝室,为了节省体力,Flymouse决定从某一个寝室出发,沿着有向路一个接一个的访问寝室并顺便发放礼物,直至能到达的所有寝室走遍为止。对于每一个寝室他可以经过无数次但是只能进入一次,进入房间会得到一个数值(数值可正可负),他想知道他能获得最大的数值和。

#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std;
const int maxn = 30000+10;
const int maxm = 150000+10;
int n,m;
struct node
{
int to;
int next;
node(){}
node(int a,int b):to(a),next(b){}
}edge[maxm];
int head[maxn],low[maxn],dfn[maxn],vis[maxn],clo[maxn],dp[maxn],w[maxn],val[maxn];
int tot,cnt,ti;
stack<int>s;
vector<int>G[maxn];
void add_edge(int a,int b)
{
edge[tot] = node(b,head[a]);
head[a] = tot++;
}
void tarjan(int u)
{
s.push(u); dfn[u] = ++ti; low[u] = ti; vis[u] = 1;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v = edge[i].to;
if(!dfn[v])
{
tarjan(v);
low[u] = min(low[u],low[v]);
}
else if(vis[v]==1)
low[u] = min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
int y; cnt++;
do{
y = s.top(); s.pop();
vis[y] = 2; clo[y] = cnt;
}while(y!=u);
}
}
int dfs(int u)
{
if(dp[u]!=-1) return dp[u];
int len = G[u].size();
int ret = 0;
for(int i=0;i<len;i++)
{
int v = G[u][i];
ret = max(ret,dfs(v));
}
return dp[u] = ret+w[u];
}
int main()
{
int u,v;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=0;i<n;i++){ scanf("%d",&val[i]);}
memset(head,-1,sizeof(head)); tot = 0;
for(int i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
add_edge(u,v);
}
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(vis,0,sizeof(vis));
memset(w,0,sizeof(w));
cnt = 0; ti = 0;
for(int i=0;i<n;i++) if(!dfn[i]) tarjan(i);
for(int i=0;i<=cnt+1;i++) G[i].clear();
for(int i=0;i<n;i++) if(val[i]>0) w[clo[i]] += val[i];
for(int i=0;i<n;i++)
{
for(int j=head[i];j!=-1;j=edge[j].next)
{
int v = edge[j].to;
if(clo[i]!=clo[v])
{
G[clo[i]].push_back(clo[v]);
}
}
}
int ans = 0; memset(dp,-1,sizeof(dp));
for(int i=1;i<=cnt;i++) ans = max(ans,dfs(i));
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: