码迷,mamicode.com
首页 > 其他好文 > 详细

UVA11324 强连通+dp记忆化搜索

时间:2015-09-10 22:26:25      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:

题意:对于一个有向图,问最大团中有多少点,要求该点集内所有点对间至少有一条路径(u到v或v到u或两条都有)。

首先,对于每一个强连通分量,其中的所有点必然能够互相到达,所以先进行缩点,然后对于缩点后的 DAG,dp[i] 表示从 i 强连通分量开始能够到达的最多的点数,那么在缩点时需要记录一下每个强连通分量的点数。然后进行DP,初始值定为该强连通分量的点数,然后用它能到达的点来更新它本身。取最大值就行了。

技术分享
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stack>
 4 #include<queue>
 5 using namespace std;
 6 
 7 const int maxn=1005;
 8 const int maxm=50005;
 9 
10 int head[2][maxn],point[2][maxm],nxt[2][maxm],size[2];
11 int n,t,scccnt;
12 int stx[maxn],low[maxn],scc[maxn],num[maxn],dp[maxn];
13 stack<int>S;
14 
15 void init(){
16     memset(head,-1,sizeof(head));
17     size[0]=size[1]=0;
18     memset(dp,0,sizeof(dp));
19 }
20 
21 void add(int a,int b,int c=0){
22     point[c][size[c]]=b;
23     nxt[c][size[c]]=head[c][a];
24     head[c][a]=size[c]++;
25 }
26 
27 void dfs(int s){
28     stx[s]=low[s]=++t;
29     S.push(s);
30     for(int i=head[0][s];~i;i=nxt[0][i]){
31         int j=point[0][i];
32         if(!stx[j]){
33             dfs(j);
34             low[s]=min(low[s],low[j]);
35         }
36         else if(!scc[j]){
37             low[s]=min(low[s],stx[j]);
38         }
39     }
40     if(low[s]==stx[s]){
41         scccnt++;
42         while(1){
43             int u=S.top();S.pop();
44             scc[u]=scccnt;
45             num[scccnt]++;
46             if(s==u)break;
47         }
48     }
49 }
50 
51 void setscc(){
52     memset(stx,0,sizeof(stx));
53     memset(scc,0,sizeof(scc));
54     memset(num,0,sizeof(num));
55     t=scccnt=0;
56     for(int i=1;i<=n;++i)if(!stx[i])dfs(i);
57     for(int i=1;i<=n;++i){
58         for(int j=head[0][i];~j;j=nxt[0][j]){
59             int k=point[0][j];
60             if(scc[i]!=scc[k]){
61                 add(scc[i],scc[k],1);
62             }
63         }
64     }
65 }
66 
67 void dfs1(int s){
68     if(dp[s])return;
69     dp[s]=num[s];
70     for(int i=head[1][s];~i;i=nxt[1][i]){
71         int j=point[1][i];
72         dfs(j);
73         if(num[s]+dp[j]>dp[s])dp[s]=num[s]+dp[j];
74     }
75 }
76 
77 int main(){
78     int T;
79     scanf("%d",&T);
80     while(T--){
81         int m;
82         scanf("%d%d",&n,&m);
83         init();
84         while(m--){
85             int a,b;
86             scanf("%d%d",&a,&b);
87             add(a,b);
88         }
89         setscc();
90         int ans=0;
91         for(int i=1;i<=scccnt;++i){
92             dfs1(i);
93             if(ans<dp[i])ans=dp[i];
94         }
95         printf("%d\n",ans);
96     }
97     return 0;
98 }
View Code

 

UVA11324 强连通+dp记忆化搜索

标签:

原文地址:http://www.cnblogs.com/cenariusxz/p/4799160.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!