UVALive4287 hdu2767 hdu3836 强连通
题意:有多个命题,需要证明他们可以互相推出,现在已经有一些证明关系即 A 可以证明 B,问至少还需要多少证明关系。
首先,如果某几个命题证明关系可以成环,那么这些命题必然可以相互证明,只要沿着环的边走就能到达其他命题,所以首先是需要强连通缩点,之后对于一个无环图,我们发现如果一个强连通分量它无出度,那么它就不能证明其他任何命题,如果它无入度,那么它就不能由任何命题证明,那么我们就需要消除这些入度或出度为0的点,其实只需要将入度为 0 的点建边指向出度为 0 的点,然后剩下多余的,入度为 0 则随意向其他点出边,出度为 0 则随意让其他点向它建边,因此所需要建的边数就是入度为 0 点数和出度为 0 点数的最大值。如果一开始图就只剩一个强连通分量,那么虽然它的入度出度都为 0 ,但已经不需要加边。
UVALive4287、hdu2767
#include<stdio.h>
#include<string.h>
#include<stack>
#include<queue>
using namespace std; const int maxn=2e4+;
const int maxm=5e4+; int head[maxn],point[maxm],nxt[maxm],size;
int n,t,scccnt;
int stx[maxn],low[maxn],scc[maxn],id[maxn],od[maxn],numi,numo;
stack<int>S; int min(int a,int b){return a<b?a:b;}
int max(int a,int b){return a>b?a:b;} void init(){
memset(head,-,sizeof(head));
size=;
} void add(int a,int b){
point[size]=b;
nxt[size]=head[a];
head[a]=size++;
} void dfs(int s){
stx[s]=low[s]=++t;
S.push(s);
for(int i=head[s];~i;i=nxt[i]){
int j=point[i];
if(!stx[j]){
dfs(j);
low[s]=min(low[s],low[j]);
}
else if(!scc[j]){
low[s]=min(low[s],stx[j]);
}
}
if(low[s]==stx[s]){
scccnt++;
while(){
int u=S.top();
S.pop();
scc[u]=scccnt;
if(s==u)break;
}
}
} void setscc(){
memset(stx,,sizeof(stx));
memset(scc,,sizeof(scc));
memset(id,,sizeof(id));
memset(od,,sizeof(od));
numi=numo=t=scccnt=;
for(int i=;i<=n;++i)if(!stx[i])dfs(i);
if(scccnt!=){
for(int i=;i<=n;++i){
for(int j=head[i];~j;j=nxt[j]){
int k=point[j];
if(scc[i]!=scc[k]){
id[scc[i]]++;
od[scc[k]]++;
if(id[scc[i]]==)numi++;
if(od[scc[k]]==)numo++;
}
}
}
numi=scccnt-numi;
numo=scccnt-numo;
}
} int main(){
int T;
scanf("%d",&T);
while(T--){
int m;
scanf("%d%d",&n,&m);
init();
while(m--){
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
}
setscc();
printf("%d\n",max(numi,numo));
}
return ;
}
hdu3836
恩,就是改下输入
#include<stdio.h>
#include<string.h>
#include<stack>
#include<queue>
using namespace std; const int maxn=2e4+;
const int maxm=5e4+; int head[maxn],point[maxm],nxt[maxm],size;
int n,t,scccnt;
int stx[maxn],low[maxn],scc[maxn],id[maxn],od[maxn],numi,numo;
stack<int>S; int min(int a,int b){return a<b?a:b;}
int max(int a,int b){return a>b?a:b;} void init(){
memset(head,-,sizeof(head));
size=;
} void add(int a,int b){
point[size]=b;
nxt[size]=head[a];
head[a]=size++;
} void dfs(int s){
stx[s]=low[s]=++t;
S.push(s);
for(int i=head[s];~i;i=nxt[i]){
int j=point[i];
if(!stx[j]){
dfs(j);
low[s]=min(low[s],low[j]);
}
else if(!scc[j]){
low[s]=min(low[s],stx[j]);
}
}
if(low[s]==stx[s]){
scccnt++;
while(){
int u=S.top();
S.pop();
scc[u]=scccnt;
if(s==u)break;
}
}
} void setscc(){
memset(stx,,sizeof(stx));
memset(scc,,sizeof(scc));
memset(id,,sizeof(id));
memset(od,,sizeof(od));
numi=numo=t=scccnt=;
for(int i=;i<=n;++i)if(!stx[i])dfs(i);
if(scccnt!=){
for(int i=;i<=n;++i){
for(int j=head[i];~j;j=nxt[j]){
int k=point[j];
if(scc[i]!=scc[k]){
id[scc[i]]++;
od[scc[k]]++;
if(id[scc[i]]==)numi++;
if(od[scc[k]]==)numo++;
}
}
}
numi=scccnt-numi;
numo=scccnt-numo;
}
} int main(){
int m;
while(scanf("%d%d",&n,&m)!=EOF){
init();
while(m--){
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
}
setscc();
printf("%d\n",max(numi,numo));
}
return ;
}
UVALive4287 hdu2767 hdu3836 强连通的更多相关文章
- UVALive-4287 Proving Equivalences 有向图的强连通分量+缩点
题意:有n个命题,已知其中的m个推导,要证明n个命题全部等价(等价具有传递性),最少还需要做出几次推导. 思路:由已知的推导可以建一张无向图,则问题变成了最少需要增加几条边能使图变成强连通图.找出所有 ...
- hdu2767 Proving Equivalences --- 强连通
给一个图,问至少加入�多少条有向边能够使图变成强连通的. 原图是有环的,缩点建图,在该DAG图上我们能够发现,要使该图变成强连通图必须连成环 而加入�最少的边连成环,就是把图上入度为0和出度为0的点连 ...
- hdu2767强连通加缩点
https://vjudge.net/contest/156688#problem/B 题目说了一大堆,前面的没有用,就是让你判断要加几条边才能强连通,用到缩点的知识 二重循环,判断邻接表下一个点是不 ...
- UVALive-4287 Proving Equivalences (有向图的强连通分量)
题目大意:有n个命题,已知其中的m个推导,要证明n个命题全部等价(等价具有传递性),最少还需要做出几次推导. 题目分析:由已知的推导可以建一张无向图,则问题变成了最少需要增加几条边能使图变成强连通图. ...
- hdu2767(图的强连通)
//题意:问需要添加几条边使得这张图成为每个点都等价(强连通图) 我们先把图中的强连通分量缩点 可能他本身就是满足条件,那么直接输出0 经过缩点后,就可以把强连通分量看成一个个独立的点,在这张图上搞一 ...
- 有向连通图增加多少边构成强联通(hdu3836,poj1236)
hdu3836 求出强分量后缩点处理得到分支图,对分支图的每个强连通分量统计出度和入度.需要的边数就是:统计 入度=0 的顶点数 和 出度=0 的顶点数,选择两者中较大的一个,才能确保一个强连通图. ...
- LA 4287 等价性证明(强连通分量缩点)
https://vjudge.net/problem/UVALive-4287 题意: 给出n个结点m条边的有向图,要求加尽量少的边,使得新图强连通. 思路:强连通分量缩点,然后统计缩点后的图的每个结 ...
- 【强连通分量】Proving Equivalences
[题目链接]hdu-2767 [题目描述] Consider the following exercise, found in a generic linear algebra textbook. L ...
- HDU5934 强连通分量
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5934 根据距离关系建边 对于强连通分量来说,只需引爆话费最小的炸弹即可引爆整个强连通分量 将所有的强连通分 ...
随机推荐
- Cisco IOS basic system management command reference
absolute : to specify an absolute time for a time-range (in time-range configuration mode) no absolu ...
- [转]Android进程与线程基本知识
转自:http://www.cnblogs.com/hanyonglu/archive/2012/04/12/2443262.html 本文介绍Android平台中进程与线程的基本知识. 很早的时候就 ...
- [C/C++]C++标准中的名词
1.qualified-id.nested-name-specifier: [example: struct A { struct B { void F(); }; }; A is an unqual ...
- Ajax get方法 IE 下乱码
每个浏览器处理编码的格式不同. ajax使用utf-8来编码发送数据,ie在发送时并没加上charset=utf-8,从而导致乱码(IE默认使用iso-8859-1编码) JavaScript代码: ...
- MongoDB 查询 (转) 仅限于C++开发
1.find MongoDB使用find来进行查询.查询就是返回一个集合中文档的子集,子集合的范围从0个文档到整个集合.find的第一个参数 决定了要返回哪些文档.其形式也是一个文档,说明要查询的细节 ...
- hdu1712 线性dp
//Accepted 400 KB 109 ms //dp线性 //dp[i][j]=max(dp[i-1][k]+a[i][j-k]) //在前i门课上花j天得到的最大分数,等于max(在前i-1门 ...
- poj1179
//Accepted 244 KB 0 ms //区间dp //石子合并模型 #include <cstdio> #include <cstring> #include < ...
- 提示错误#165 too few argument in function call
调用函数时,参数个数少于函数定义.检查一下函数定义和参数调用,两个要一致.
- Math 对象的方法
Math 对象的方法 方法 描述 abs(x) 返回数的绝对值 acos(x) 返回数的反余弦值 asin(x) 返回数的反正弦值 atan(x) 以介于 -PI/2 与 PI/2 弧度之间的数值来返 ...
- Osmocom-BB中cell_log的多种使用姿势
转载留做备份,原文地址:http://92ez.com/?action=show&id=23342 翻阅osmocom-bb源码的时候注意到,在cell_log中有非常多我们从来没有注意到的功 ...