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

UVALive4287 hdu2767 hdu3836 强连通

时间:2015-09-10 22:28:44      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:

题意:有多个命题,需要证明他们可以互相推出,现在已经有一些证明关系即 A 可以证明 B,问至少还需要多少证明关系。

首先,如果某几个命题证明关系可以成环,那么这些命题必然可以相互证明,只要沿着环的边走就能到达其他命题,所以首先是需要强连通缩点,之后对于一个无环图,我们发现如果一个强连通分量它无出度,那么它就不能证明其他任何命题,如果它无入度,那么它就不能由任何命题证明,那么我们就需要消除这些入度或出度为0的点,其实只需要将入度为 0 的点建边指向出度为 0 的点,然后剩下多余的,入度为 0 则随意向其他点出边,出度为 0 则随意让其他点向它建边,因此所需要建的边数就是入度为 0 点数和出度为 0 点数的最大值。如果一开始图就只剩一个强连通分量,那么虽然它的入度出度都为 0 ,但已经不需要加边。

UVALive4287、hdu2767

技术分享
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stack>
 4 #include<queue>
 5 using namespace std;
 6 
 7 const int maxn=2e4+5;
 8 const int maxm=5e4+5;
 9 
10 int head[maxn],point[maxm],nxt[maxm],size;
11 int n,t,scccnt;
12 int stx[maxn],low[maxn],scc[maxn],id[maxn],od[maxn],numi,numo;
13 stack<int>S;
14 
15 int min(int a,int b){return a<b?a:b;}
16 int max(int a,int b){return a>b?a:b;}
17 
18 void init(){
19     memset(head,-1,sizeof(head));
20     size=0;
21 }
22 
23 void add(int a,int b){
24     point[size]=b;
25     nxt[size]=head[a];
26     head[a]=size++;
27 }
28 
29 void dfs(int s){
30     stx[s]=low[s]=++t;
31     S.push(s);
32     for(int i=head[s];~i;i=nxt[i]){
33         int j=point[i];
34         if(!stx[j]){
35             dfs(j);
36             low[s]=min(low[s],low[j]);
37         }
38         else if(!scc[j]){
39             low[s]=min(low[s],stx[j]);
40         }
41     }
42     if(low[s]==stx[s]){
43         scccnt++;
44         while(1){
45             int u=S.top();
46             S.pop();
47             scc[u]=scccnt;
48             if(s==u)break;
49         }
50     }
51 }
52 
53 void setscc(){
54     memset(stx,0,sizeof(stx));
55     memset(scc,0,sizeof(scc));
56     memset(id,0,sizeof(id));
57     memset(od,0,sizeof(od));
58     numi=numo=t=scccnt=0;
59     for(int i=1;i<=n;++i)if(!stx[i])dfs(i);
60     if(scccnt!=1){
61         for(int i=1;i<=n;++i){
62             for(int j=head[i];~j;j=nxt[j]){
63                 int k=point[j];
64                 if(scc[i]!=scc[k]){
65                     id[scc[i]]++;
66                     od[scc[k]]++;
67                     if(id[scc[i]]==1)numi++;
68                     if(od[scc[k]]==1)numo++;
69                 }
70             }
71         }
72         numi=scccnt-numi;
73         numo=scccnt-numo;
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         printf("%d\n",max(numi,numo));
91     }
92     return 0;
93 }
94         
View Code

 

hdu3836

恩,就是改下输入

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

 

UVALive4287 hdu2767 hdu3836 强连通

标签:

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

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