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 }