HDU - 2767 Proving Equivalences tanjar强连通-DAG性质
传送门
很开心,wrong了十多发。因为不认真写错了一个字母,找了一个晚上的bug。
题意:给你一个单向图,问你加多少边能够变成一个强连通图,很显然首先是通过tanjar缩点将该图转化为了DAG,看了博客发现了一个很重要的性质,对于某个DAG加多少条边能成为强连通。
边数=max(入度为0的点个数,初度为0的点个数)
为啥呢?首先我们假设可以自己想象一哈,每一个DAG图可以看作树的元素。设入度为0的点(即树的根)个数为a,对于每一个出度为0的点(即树的以叶子节点)个数为b。如果要成为强连通图,我们必须从叶子节点引出一条边,也必须对一个根引入一条边。
哦吼,那么不是说我从出度为0的点引出一条边到入度为0的点,那么这些就构成了环。所以剩下的abs(a-b)的入度为0,出度为0的点随便连接一条边到树里的任意元素就可以喽,所以边数=min(a,b)+abs(a-b)=max(a,b);这就是上边大字的验证。
所以呢,可以不用建新的图,但是当本身就是强连通图时,cnt==1,就不需要边了,特判一哈。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<stack>
#include<vector>
#include<map>
#include<queue>
#define myself i,l,r
#define lson i<<1
#define rson i<<1|1
#define Lson i<<1,l,mid
#define Rson i<<1|1,mid+1,r
#define half (l+r)/2
#define inff 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define me(a,b) memset(a,b,sizeof(a))
#define min4(a,b,c,d) min(min(a,b),min(c,d))
#define min3(x,y,z) min(min(x,y),min(y,z))
typedef long long ll;
using namespace std;
const int maxn=2e4+4;
const int maxnn=5e4+4;
int cnt,top,t,sign,n,m;
int head[maxn],low[maxn],dfn[maxn],Stack[maxn],inStack[maxn];
int in[maxn],out[maxn],belong[maxn];
struct node
{int to,p;
}edge[maxnn];
void add(int u,int v)
{edge[sign]=node{v,head[u]};head[u]=sign++;
}
void init()
{cnt=top=t=sign=0;for(int i=0;i<=n;i++){in[i]=out[i]=0;low[i]=dfn[i]=inStack[i]=0;head[i]=-1;}
}
void tanjar(int u)
{low[u]=dfn[u]=++t;Stack[++top]=u;inStack[u]=1;for(int i=head[u];i!=-1;i=edge[i].p){int v=edge[i].to;if(!dfn[v]){tanjar(v);low[u]=min(low[u],low[v]);}else if(inStack[v])low[u]=min(low[u],dfn[v]);}int x;if(low[u]==dfn[u]){cnt++;do{x=Stack[top--];inStack[x]=0;belong[x]=cnt;}while(x!=u);}
}
int main()
{int T,x,y;scanf("%d",&T);while(T--){scanf("%d %d",&n,&m);init();while(m--){scanf("%d %d",&x,&y);add(x,y);}for(int i=1;i<=n;i++){if(!dfn[i])tanjar(i);}if(cnt==1)cout<<0<<endl;else{for(int i=1;i<=n;i++){for(int j=head[i];j!=-1;j=edge[j].p){int e=edge[j].to;if(belong[i]!=belong[e]){in[belong[e]]=1;out[belong[i]]=1;}}}int a=0,b=0;for(int i=1;i<=cnt;i++){if(in[i]==0) a++;if(out[i]==0) b++;}printf("%d\n",max(a,b));}}return 0;
}
HDU - 2767 Proving Equivalences tanjar强连通-DAG性质相关推荐
- hdu 2767 Proving Equivalences (加多少边使其强连通)
题意大致是有n个 推断,和m个推出关系,输入a b代表a能推出b,问要使n个推断能够互相推出,至少要证明几个推断.a推出b,在图中是由a指向b的有向边,能够相互推出,即加最少的边使图变成强连通图 思路 ...
- hdu - 2667 Proving Equivalences(强连通)
http://acm.hdu.edu.cn/showproblem.php?pid=2767 求至少添加多少条边才能变成强连通分量.统计入度为0的点和出度为0的点,取最大值即可. 1 #include ...
- 有向图 加最少的边 成为强连通分量的证明 poj 1236 hdu 2767
poj 1236: 题目大意:给出一个有向图, 任务一: 求最少的点,使得从这些点出发可以遍历整张图 任务二: 求最少加多少边 使整个图变成一个强连通分量. 首先任务一很好做, 只要缩点 之后 求 ...
- UVa 12167 HDU 2767 强连通分量 Proving Equivalences
题意:给出一个有向图,问最少添加几条有向边使得原图强连通. 解法:求出SCC后缩点,统计一下出度为0的点和入度为0的点,二者取最大值就是答案. 还有个特殊情况就是本身就是强连通的话,答案就是0. 1 ...
- 【强连通分量】Proving Equivalences
[题目链接]hdu-2767 [题目描述] Consider the following exercise, found in a generic linear algebra textbook. L ...
- HDU 5934:Bomb(强连通缩点)
http://acm.hdu.edu.cn/showproblem.php?pid=5934 题意:有N个炸弹,每个炸弹有一个坐标,一个爆炸范围和一个爆炸花费,如果一个炸弹的爆炸范围内有另外的炸弹,那 ...
- 【HDU - 5934】Bomb (强连通分量Tarjan + 缩点)
题干: There are NN bombs needing exploding. Each bomb has three attributes: exploding radius riri, pos ...
- hdu 1271 小希的迷宫(树的性质,并查集)
小希的迷宫 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Subm ...
- hdu 1269(Tarjan求强连通分量)
这道题目就是求强连通分量... 这里采用的是Tarjan算法:http://m.blog.csdn.net/blog/qq574857122/16361033 AC代码: #include<io ...
最新文章
- 新型量子计算机首个基本元件问世,扩展性更强运算速度更快
- XLNet再次超越BERT,技术发展太快,如何才能跟得上节奏?
- android 麦克风耳机,Android force AudioRecord使用耳机麦克风
- Spring Boot API 接口文档 Swagger 入门
- 快钱接口php,快钱支付接口
- alter table add column多个字段_ElementUI表格el-table表头固定自适应高度解决方案
- wireshark windows版数据过滤插件安装及使用
- 微信支付php案例,小程序微信支付php案例
- 为什么要使用MQ消息中间件?
- c语言 停车管理系统
- Android 身份证号码校验
- flash遮罩动画的使用技巧
- 比特红:万物可直播、人人能带货
- (python)bing搜索引擎API接入测试
- 基于 Ubuntu 玩转 Hudi Docker Demo (2)—— 测试数据写入 Kafka
- 无人驾驶计算机控制系统,自动驾驶汽车的无人驾驶系统三大模块是什么?
- quark h5 学习
- Zepto中文API
- linux 重试密码次数超,Linux中密码策略
- 输出魔方阵,所谓魔方阵是指这样的方阵,它的每一行,每一列和对角线之和均相等。例如,三阶魔方阵为