题目来源: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
  1 # include<stdio.h>
2 # include<string.h>
3 # include<queue>
4 # define N 30005
5 # define M 150005
6 using namespace std;
7 struct node{
8 int from,next,to;
9 }edge1[M],edge2[M],edge[M];
10 int head[N],tol1,head1[N],head2[N],tol2,val[N],visit1[N],visit2[N],V[N],tol;
11 int T[N],Belong[N],DP[N],in[N],Tcnt,Bcnt,Max,visit[N];
12 queue<int>S;
13 void Add(int a,int b)
14 {
15 edge1[tol1].from=a;edge1[tol1].to=b;edge1[tol1].next=head1[a];head1[a]=tol1++;
16 edge2[tol2].from=b;edge2[tol2].to=a;edge2[tol2].next=head2[b];head2[b]=tol2++;
17 }
18 void add(int a,int b)
19 {
20 edge[tol].from=a;edge[tol].to=b;edge[tol].next=head[a];head[a]=tol++;
21 }
22 void dfs1(int i)
23 {
24 int j,v;
25 visit1[i]=1;
26 for(j=head1[i];j!=-1;j=edge1[j].next)
27 {
28 v=edge1[j].to;
29 if(!visit1[v]) dfs1(v);
30 }
31 T[Tcnt++]=i;
32 }
33 void dfs2(int i)
34 {
35 int j,v;
36 visit2[i]=1;
37 Belong[i]=Bcnt;
38 if(val[i]>0) V[Bcnt]+=val[i];
39 for(j=head2[i];j!=-1;j=edge2[j].next)
40 {
41 v=edge2[j].to;
42 if(!visit2[v]) dfs2(v);
43 }
44 }
45 int main()
46 {
47 int i,n,m,a,b,j,v,cur;
48 while(scanf("%d%d",&n,&m)!=EOF)
49 {
50 for(i=0;i<n;i++)
51 scanf("%d",&val[i]);
52 tol1=tol2=0;
53 memset(head1,-1,sizeof(head1));
54 memset(head2,-1,sizeof(head2));
55 for(i=0;i<m;i++)
56 {
57 scanf("%d%d",&a,&b);
58 Add(a,b);
59 }
60 memset(visit1,0,sizeof(visit1));
61 memset(visit2,0,sizeof(visit2));
62 memset(V,0,sizeof(V));
63 Tcnt=Bcnt=0;
64 for(i=0;i<n;i++)
65 if(!visit1[i]) dfs1(i);
66 for(i=Tcnt-1;i>=0;i--)
67 {
68 if(!visit2[T[i]])
69 {
70 dfs2(T[i]);
71 Bcnt++;
72 }
73 }
74 tol=0;
75 memset(head,-1,sizeof(head));
76 memset(in,0,sizeof(in));
77 for(i=0;i<m;i++)
78 {
79 a=edge1[i].from;
80 b=edge1[i].to;
81 if(Belong[a]==Belong[b]) continue;
82 add(Belong[b],Belong[a]);//建立反向边
83 in[Belong[a]]++;
84 }
85 memset(DP,0,sizeof(DP));
86 Max=0;
87 memset(visit,0,sizeof(visit));
88 for(i=0;i<Bcnt;i++)
89 {
90 if(in[i]==0)
91 S.push(i);
92 }
93 while(!S.empty())
94 {
95 cur=S.front();
96 S.pop();
97 for(j=head[cur];j!=-1;j=edge[j].next)
98 {
99 v=edge[j].to;
100 if(visit[v]<V[cur]) visit[v]=V[cur];
101 in[v]--;
102 if(in[v]==0)
103 {
104 V[v]+=visit[v];
105 S.push(v);
106 }
107 }
108 if(V[cur]>Max) Max=V[cur];
109 }
110 printf("%d\n",Max);
111 }
112 return 0;
113 }

 

posted on 2011-09-26 17:55  奋斗青春  阅读(923)  评论(0编辑  收藏  举报