您的位置:首页 > 其它

pku 3160 Father Christmas flymouse

2011-09-26 17:55 447 查看
题目来源:http://poj.org/problem?id=3160

强连通+DP

题目大意:圣诞节要到了,flymouse要给他的队友们送去礼物,,n个队友住在n个不同的房子里,每个队友住的地方都有一个comfort index (positive or negative);

他每给一个队友送去礼物,都将得到该队友的comfort index ,问最后他能获得的maximized sum of accumulated comfort indices;

不过题目还有其他的要求:follow directed paths to visit one room after another and give out gifts en passant until he could reach no more unvisited rooms。

思路:根据题目要求,可以先进行缩点,因为一个强连通分量里面的所有点,如果能访问其中一个那这个分量里面的所有点都能访问到, 题目要求最大,所以只访问权值为正的点。

缩点之后的每个点都有一个非负的权值。

下面可以有两种解法:

1. 再重新建图,从入读为0的点开始先下访问,找到最大值。

2. 建立反向图,下面就利用拓扑排序的思想。

很明显2的效率要高一点。

2的代码:

View Code

# include<stdio.h>
# include<string.h>
# include<queue>
# define N 30005
# define M 150005
using namespace std;
struct node{
int from,next,to;
}edge1[M],edge2[M],edge[M];
int head
,tol1,head1
,head2
,tol2,val
,visit1
,visit2
,V
,tol;
int T
,Belong
,DP
,in
,Tcnt,Bcnt,Max,visit
;
queue<int>S;
void Add(int a,int b)
{
edge1[tol1].from=a;edge1[tol1].to=b;edge1[tol1].next=head1[a];head1[a]=tol1++;
edge2[tol2].from=b;edge2[tol2].to=a;edge2[tol2].next=head2[b];head2[b]=tol2++;
}
void add(int a,int b)
{
edge[tol].from=a;edge[tol].to=b;edge[tol].next=head[a];head[a]=tol++;
}
void dfs1(int i)
{
int j,v;
visit1[i]=1;
for(j=head1[i];j!=-1;j=edge1[j].next)
{
v=edge1[j].to;
if(!visit1[v]) dfs1(v);
}
T[Tcnt++]=i;
}
void dfs2(int i)
{
int j,v;
visit2[i]=1;
Belong[i]=Bcnt;
if(val[i]>0) V[Bcnt]+=val[i];
for(j=head2[i];j!=-1;j=edge2[j].next)
{
v=edge2[j].to;
if(!visit2[v]) dfs2(v);
}
}
int main()
{
int i,n,m,a,b,j,v,cur;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=0;i<n;i++)
scanf("%d",&val[i]);
tol1=tol2=0;
memset(head1,-1,sizeof(head1));
memset(head2,-1,sizeof(head2));
for(i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
Add(a,b);
}
memset(visit1,0,sizeof(visit1));
memset(visit2,0,sizeof(visit2));
memset(V,0,sizeof(V));
Tcnt=Bcnt=0;
for(i=0;i<n;i++)
if(!visit1[i]) dfs1(i);
for(i=Tcnt-1;i>=0;i--)
{
if(!visit2[T[i]])
{
dfs2(T[i]);
Bcnt++;
}
}
tol=0;
memset(head,-1,sizeof(head));
memset(in,0,sizeof(in));
for(i=0;i<m;i++)
{
a=edge1[i].from;
b=edge1[i].to;
if(Belong[a]==Belong[b]) continue;
add(Belong[b],Belong[a]);//建立反向边
in[Belong[a]]++;
}
memset(DP,0,sizeof(DP));
Max=0;
memset(visit,0,sizeof(visit));
for(i=0;i<Bcnt;i++)
{
if(in[i]==0)
S.push(i);
}
while(!S.empty())
{
cur=S.front();
S.pop();
for(j=head[cur];j!=-1;j=edge[j].next)
{
v=edge[j].to;
if(visit[v]<V[cur]) visit[v]=V[cur];
in[v]--;
if(in[v]==0)
{
V[v]+=visit[v];
S.push(v);
}
}
if(V[cur]>Max) Max=V[cur];
}
printf("%d\n",Max);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: