BZOJ 1638 [Usaco2007 Mar]Cow Traffic 奶牛交通:记忆化搜索【图中边的经过次数】

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1638

题意:

  给你一个有向图,n个点,m条有向边。

  对于所有从入度为0的点到n的路径,找出被经过次数最多的一条边,输出这个次数。

 

题解:

  edge为原边,redge为反向边。

 

  cnt[i]表示从入度为0的点到i的路径数。

  rev[i]表示从i到n的路径数。

  两遍记忆化搜索,处理出数组cnt和rev。

 

  每条边(a,b)被经过的次数 = cnt[a]*rev[b]

  扫一遍取最大,即为答案。

 

AC Code:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <vector>
 5 #define MAX_N 5005
 6 
 7 using namespace std;
 8 
 9 int n,m;
10 int ans=0;
11 int cnt[MAX_N];
12 int rev[MAX_N];
13 vector<int> edge[MAX_N];
14 vector<int> redge[MAX_N];
15 
16 void read()
17 {
18     cin>>n>>m;
19     int a,b;
20     for(int i=0;i<m;i++)
21     {
22         cin>>a>>b;
23         edge[a].push_back(b);
24         redge[b].push_back(a);
25     }
26 }
27 
28 void dfs(int now,int *cnt,const vector<int> *edge)
29 {
30     if(cnt[now]!=-1) return;
31     if(!edge[now].size())
32     {
33         cnt[now]=1;
34         return;
35     }
36     cnt[now]=0;
37     for(int i=0;i<edge[now].size();i++)
38     {
39         int temp=edge[now][i];
40         dfs(temp,cnt,edge);
41         cnt[now]+=cnt[temp];
42     }
43 }
44 
45 void solve()
46 {
47     memset(cnt,-1,sizeof(cnt));
48     memset(rev,-1,sizeof(rev));
49     for(int i=1;i<=n;i++)
50     {
51         if(rev[i]==-1) dfs(i,rev,edge);
52     }
53     dfs(n,cnt,redge);
54     for(int i=1;i<=n;i++)
55     {
56         for(int j=0;j<edge[i].size();j++)
57         {
58             int temp=edge[i][j];
59             ans=max(ans,cnt[i]*rev[temp]);
60         }
61     }
62 }
63 
64 void print()
65 {
66     cout<<ans<<endl;
67 }
68 
69 int main()
70 {
71     read();
72     solve();
73     print();
74 }

 

posted @ 2017-10-07 18:03  Leohh  阅读(170)  评论(0编辑  收藏  举报