Proving Equivalences HDU
来源:互联网 发布:党规党纪面前知敬畏守 编辑:程序博客网 时间:2024/06/16 14:12
题意:给一个有向图,问至少加多少条边后可以变成强联通图
思路:先用tarjan来缩点,然后计算缩点之后的入度为0的点,和出度为0的点,ans等于他们之间的最大值。
为什么是最大值?
缩点之后是有向无环图,可以看成若干链组成,入度为0的点(n个)表示链的开头,出度为0的点(m个)表示链的结尾。先入度和出度连起来(连min(n,m)-1条边),使之成为一条链。
一条链,连头尾,比如有3头(入度为0)2尾,先将2头两尾连起来,使成为两个环,然后缩点后,为一头一尾,连起来就行了。
一条链,的头为 n-min(n,m)+1,尾为m-min(n,m)+1。连头尾的max条边。
所以ans为入度为0与出度为0的最大值。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <vector>#include <set>#include <map>using namespace std;#define ll long long#define mem(a,b) memset(a,b,sizeof(a))const int maxn = 20010;const int maxm = 50010;int sd[maxn],rd[maxn],cd[maxn],dian[maxn],head[maxn],low[maxn],dfn[maxn],st[maxn],vis_st[maxn];struct node{ int to,pre;}e[maxm];void ini(){ mem(st,0);mem(dfn,0);mem(low,0);mem(vis_st,0);mem(e,0);mem(sd,0);mem(rd,0);mem(cd,0);mem(dian,0);mem(head,-1);}void addedge(int h,int a,int b){ e[h].to=b;e[h].pre=head[a];head[a]=h;}int top=0,tot=0,num=0;void Tarjan(int u){ st[++top]=u; dfn[u]=low[u]=++tot; vis_st[u]=1; for(int i=head[u];i>-1;i=e[i].pre) { node t=e[i]; if(!dfn[t.to]) { Tarjan(t.to); low[u]=min(low[u],low[t.to]); } else {if(vis_st[t.to]) low[u]=min(low[u],low[t.to]);} } if(dfn[u]==low[u]) { sd[num++]=u; int a; do{ a=st[top--]; vis_st[a]=0; dian[a]=u;//这里不小心打错了。。。wa了好久。。 }while(u!=a); }}int main(){ int n; scanf("%d",&n); while(n--) { int N,M; scanf("%d %d",&N,&M); ini();int h=0; num=top=tot=0; for(int i=0;i<M;i++) { int a,b; scanf("%d %d",&a,&b); addedge(h,a,b);h++; } for(int i=1;i<=N;i++) if(!dfn[i])//不用vis直接dfn,而且也不用初始化。如果初始化,会T。 Tarjan(i); if(num==1) printf("0\n"); else{ for(int i=1;i<=N;i++) { for(int j=head[i];j>-1;j=e[j].pre) { node t=e[j]; if(dian[t.to]==dian[i]) continue; cd[dian[i]]++; rd[dian[e[j].to]]++; } } int ans1=0,ans2=0; for(int i=0;i<num;i++) { if(cd[sd[i]]==0) ans1++; if(rd[sd[i]]==0) ans2++; } printf("%d\n",max(ans1,ans2)); } } return 0;}
阅读全文
0 0
- HDU 2767 Proving Equivalences
- HDU 2767 Proving Equivalences
- hdu 2767 Proving Equivalences
- HDU 2767 Proving Equivalences
- HDU 2767 Proving Equivalences
- hdu 2767 Proving Equivalences
- HDU 2767 Proving Equivalences
- HDU 2767 Proving Equivalences
- hdu 2767 Proving Equivalences
- HDU 2767 Proving Equivalences
- hdu 2767 Proving Equivalences
- Proving Equivalences HDU
- Proving Equivalences HDU
- Proving Equivalences HDU
- Proving Equivalences
- Proving Equivalences
- hdu 2767 Proving Equivalences (tarjan + 缩点)
- hdu 2767 Proving Equivalences(强连通分量)
- openlayers4中闪烁点的实现
- Algorithm-week4
- Qt 之 模仿 QQ登陆界面——功能篇(一)
- Codeforces 454D Little Pony and Harmony Chest【思维+状压Dp+记录路径】好题!
- Java类初始化顺序
- Proving Equivalences HDU
- Pixhawk飞行模式的讨论
- 集合类
- Divisors POJ
- HDOJ2054(大数处理)
- C++常见面试题(一)C/C++区别 const用法
- 文件操作——File
- 【网页--HTML使用教程】
- Java SE8 Lambda 基础入门---lambda表达式的类型是什么