首页 > 试题

强连通分量

更新时间:2022-12-10 07:50:34 阅读: 评论:0

几何做题思路-如的组词


2022年12月10日发(作者:激活win7旗舰版)

等价性证明(强连通分量+缩点)

【问题描述】

在数学中,我们常常需要完成若⼲命题的等价性证明。

例如:有4个命题a,b,c,d,要证明他们是等价的,我们需要证明a<=>b,然后b<=>c,最后c<=>d。注意每次证明是双向的,因此⼀共

完成了6次推导。另⼀种证明⽅法是:证明a->b,然后b->c,接着c->d,最后d->a,只须4次证明。

现在你任务是证明n个命题全部等价,且你的朋友已经为你作出了m次推导(已知每次推导的内容),你⾄少还需做⼏次推导才能完成

整个证明。

【输⼊格式】

有T组数据,每组数据第⼀⾏为两个整数n和m,即命题数和已完成的推导个数(编号为1..n)。以下m⾏每⾏包含两个整数s1和

s2(1<=s1,s2<=n,s1!=s2),表明已经证明了s1->s2。

【输出格式】

输出还需要做推导数的最⼩值。

【输⼊样例】

2

40

32

12

13

【输出样例】

4

2

【数据范围】

T<=100

1<=n<=20000

0<=m<=50000

分析:

1.分析可知,如给出A->B,那么需要找⼀系列推导推出B->A,即找⼀条路从B回到A,也就是找环,求强连通分量;

2.求出所有分量后,分量内部所有的都可以互相推出,不⽤考虑,只需考虑不同分量内的,所以缩点;

3.缩点后形成DAG图,要整个图变成强联通图,需要“消灭”⼊度或者出度为0的点,因此分别统计出度和⼊度为0的点,求⼤的⼀个答案

即可;

4.坑点:当整个图就是强联通图时,输出0;

代码:(菜鸡为了节约memt的时间⽤了结构体存时间,请忽视.....)

#include

#include

#include

usingnamespacestd;

constintmaxn=20005;

constintmaxm=50005;

intn,m,T,np=0,Time,last[maxn];

structedge{intto,pre;}E[maxm];

structdata{inttime,num;};

charc;

voidqkscanf(int&x)

{

for(c=getchar();c<'0'||c>'9';c=getchar());

for(x=0;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';

}

voidaddedge(intu,intv)

{

E[++np]=(edge){v,last[u]};

last[u]=np;

}

intstk[maxn],top,dfs_clock,rd[maxn],cd[maxn],scc_cnt;

datadfn[maxn],low[maxn],belong[maxn];

voidDFS(inti)

{

dfn[i]=low[i]=(data){Time,++dfs_clock};

rd[i]=0,cd[i]=0;

stk[++top]=i;

for(intp=last[i];p;p=E[p].pre)

{

intj=E[p].to;

if(dfn[j].num&&dfn[j].time==Time)

{

if(!belong[j].num||belong[j].time!=Time)

{

low[i].num=min(low[i].num,dfn[j].num);

}

continue;

}

DFS(j);

low[i].num=min(low[i].num,low[j].num);

}

if(low[i].num==dfn[i].num)

{

scc_cnt++;

while(1)

{

intx=stk[top--];

belong[x]=(data){Time,scc_cnt};

if(x==i)break;

}

}

}

voidsuodian()

{

{

for(inti=1;i<=n;i++)

{

for(intp=last[i];p;p=E[p].pre)

{

intj=E[p].to;

if(belong[i].num!=belong[j].num)

{

cd[belong[i].num]++;

rd[belong[j].num]++;

}

}

}

}

voidinit()

{

memt(last,0,sizeof(last));

np=0;top=0;dfs_clock=0;scc_cnt=0;

}

intmain()

{

//freopen("","r",stdin);

qkscanf(T);

intu,v;

for(Time=1;Time<=T;Time++)

{

init();//初始化

qkscanf(n);qkscanf(m);

for(inti=1;i<=m;i++)

{

qkscanf(u);qkscanf(v);

addedge(u,v);

}

for(inti=1;i<=n;i++)if(!dfn[i].num||dfn[i].time!=Time)DFS(i);//求出连通分量

suodian();//缩点

inta=0,b=0;//统计出度、⼊度为0的点

for(inti=1;i<=scc_cnt;i++)

{

if(rd[i]==0)a++;

if(cd[i]==0)b++;

}

printf("%dn",scc_cnt==1?0:max(a,b));

}

return0;

}

本文发布于:2022-12-10 07:50:34,感谢您对本站的认可!

本文链接:http://www.wtabcd.cn/fanwen/fan/88/77866.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:脂肪烃
下一篇:lastly
标签:强连通分量
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图