您的位置:首页 > 其它

hiho一下 第五十四周 (缩点+dfs)

2015-07-13 15:56 225 查看
这道题错了好几次,没有看到一定从1号开始走。

题目的意思就是问你从一号开始走,最多可以吃多少草。

直接用到有向图的双连通的trajan算法给图缩点,

再重新新建一个缩完点之后的图,

然后直接从1号开始dfs就可以了。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stack>
using namespace std;
const int N=20010;
const int M=200020;
int pnt[M],nxt[M],head[M],e;
int pnt1[M],nxt1[M],head1[M],e1;
int low
,dfn
,belong
,pan
,st
;
int cost
;
int n,m,top,depth,cnt;
long long sum,maxk,num
;

void AddEdge(int u,int v)
{
pnt[e]=v;
nxt[e]=head[u];
head[u]=e++;
}
void AddEdge2(int u,int v)
{
pnt1[e]=v;
nxt1[e]=head1[u];
head1[u]=e++;
}
void init()
{
cnt=top=depth=0;
e=0;
e1=0;
sum=0;
maxk=0;
memset(head,-1,sizeof(head));
memset(head1,-1,sizeof(head1));
memset(dfn,0,sizeof(dfn));
memset(num,0,sizeof(num));

for(int i=0; i<=n; i++)
pan[i]=belong[i]=0;
}
void dfs(int now)
{
st[top++]=now;
dfn[now]=low[now]=++depth;
pan[now]=1;
for(int i=head[now]; i!=-1; i=nxt[i])
{
if(!dfn[pnt[i]])
{
dfs(pnt[i]);
low[now]=min(low[now],low[pnt[i]]);
}
else if(pan[pnt[i]])//遇到回边的处理,如果是之前已经处理过的强连通分量的点就不管了。
low[now]=min(low[now],dfn[pnt[i]]);
}
if(low[now]==dfn[now])
{
cnt++;
int j;
while(j=st[--top])
{
pan[st[top]]=0;
belong[st[top]]=cnt;
if(j==now)break;
}
}
return ;
}
void dfs2(int u,long long cc)
{
//printf("%d ",u);
if(sum<cc)sum=cc;
for(int i=head1[u]; i!=-1; i=nxt1[i])
{
int v=pnt1[i];
dfs2(v,cc+num[v]);
}
}
void print()
{
for(int i=1; i<=n; i++)
num[belong[i]]+=cost[i];
for(int u=1; u<=n; u++)
{
for(int i=head[u]; i!=-1; i=nxt[i])
{
int v=pnt[i];
if(belong[u]!=belong[v])
{
// printf("ss %d %d\n",belong[u],belong[v]);
AddEdge2(belong[u],belong[v]);
}
}
}
sum=0;
dfs2(belong[1],num[belong[1]]);//1号点变成了变成缩点的belong[1]值。
maxk=max(maxk,sum);

printf("%d\n",maxk);
}
int main()
{
scanf("%d%d",&n,&m);
init();
for(int i=1; i<=n; i++)
scanf("%d",&cost[i]);
int u,v;
for(int i=0; i<m; i++)
{
scanf("%d%d",&u,&v);
AddEdge(u,v);
}
for(int i=1; i<=n; i++)
if(!dfn[i])
dfs(i);
print();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: