题意:有多个命题,需要证明他们可以互相推出,现在已经有一些证明关系即 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 强连通的更多相关文章

  1. UVALive-4287 Proving Equivalences 有向图的强连通分量+缩点

    题意:有n个命题,已知其中的m个推导,要证明n个命题全部等价(等价具有传递性),最少还需要做出几次推导. 思路:由已知的推导可以建一张无向图,则问题变成了最少需要增加几条边能使图变成强连通图.找出所有 ...

  2. hdu2767 Proving Equivalences --- 强连通

    给一个图,问至少加入�多少条有向边能够使图变成强连通的. 原图是有环的,缩点建图,在该DAG图上我们能够发现,要使该图变成强连通图必须连成环 而加入�最少的边连成环,就是把图上入度为0和出度为0的点连 ...

  3. hdu2767强连通加缩点

    https://vjudge.net/contest/156688#problem/B 题目说了一大堆,前面的没有用,就是让你判断要加几条边才能强连通,用到缩点的知识 二重循环,判断邻接表下一个点是不 ...

  4. UVALive-4287 Proving Equivalences (有向图的强连通分量)

    题目大意:有n个命题,已知其中的m个推导,要证明n个命题全部等价(等价具有传递性),最少还需要做出几次推导. 题目分析:由已知的推导可以建一张无向图,则问题变成了最少需要增加几条边能使图变成强连通图. ...

  5. hdu2767(图的强连通)

    //题意:问需要添加几条边使得这张图成为每个点都等价(强连通图) 我们先把图中的强连通分量缩点 可能他本身就是满足条件,那么直接输出0 经过缩点后,就可以把强连通分量看成一个个独立的点,在这张图上搞一 ...

  6. 有向连通图增加多少边构成强联通(hdu3836,poj1236)

    hdu3836 求出强分量后缩点处理得到分支图,对分支图的每个强连通分量统计出度和入度.需要的边数就是:统计 入度=0 的顶点数 和 出度=0 的顶点数,选择两者中较大的一个,才能确保一个强连通图. ...

  7. LA 4287 等价性证明(强连通分量缩点)

    https://vjudge.net/problem/UVALive-4287 题意: 给出n个结点m条边的有向图,要求加尽量少的边,使得新图强连通. 思路:强连通分量缩点,然后统计缩点后的图的每个结 ...

  8. 【强连通分量】Proving Equivalences

    [题目链接]hdu-2767 [题目描述] Consider the following exercise, found in a generic linear algebra textbook. L ...

  9. HDU5934 强连通分量

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5934 根据距离关系建边 对于强连通分量来说,只需引爆话费最小的炸弹即可引爆整个强连通分量 将所有的强连通分 ...

随机推荐

  1. 高效率JAVA实现斐波那契

    import java.util.Scanner;public class Solution { public static int Fibonacci(int n) { int first = 0, ...

  2. jsp福利哟

    Servlet与JSP九大内置对象的关系 JSP对象 怎样获得 out->response.getWriter request ->Service方法中的req参数 response -& ...

  3. 解决uploadify多图片上传部分图片丢失,且不提示任何错误的问题

    这两天用到uploadify的flash版本进行批量图片上传并生成缩略图的功能,之前用uploadify用的好好的,这次突然出现了一个奇怪的问题. 问题描述如下:当我选择单个图片上传的时候,图片上传都 ...

  4. 跨域请求之jQuery的ajax jsonp的使用解惑

    前天在项目中写的一个ajax jsonp的使用,出现了问题:可以成功获得请求结果,但没有执行success方法,直接执行了error方法提示错误——ajax jsonp之前并没有用过,对其的理解为跟普 ...

  5. 《hanoi(汉诺塔)问题》求解

    //Hanoi(汉诺)塔问题.这是一个古典的数学问题,用递归方法求解.问题如下: /* 古代有一个梵塔,塔内有3个座A,B,C,开始时A座上有64个盘子,盘子大小不等,大的在下,小的在上. 有一个老和 ...

  6. javascript正则表达式替换字符串

    var reg = /^per_list(.*)[\d]{1,}(.*)/;var str = "per_listAmtApril1.value";var replaceStr = ...

  7. 迪士尼黑科技:爬墙机器人 VertiGo

    12 月 30 日,迪士尼研发出的一款爬墙机器人曝光了一段有趣的视频.从视频里可看出这个机器人碰到墙壁时迅速地作出反应爬了上去. 据了解,这个爬墙机器人名叫 VertiGo,由迪士尼研究中心和苏黎世联 ...

  8. 爬虫学习----获取cookie

    http://blog.csdn.net/samxx8/article/details/21535901 1.获取cookie import urllib import http.cookiejarc ...

  9. 黑马程序员——【Java基础】——面向对象(一)概述、类与对象、继承、抽象类、接口、多态、内部类

    ---------- android培训.java培训.期待与您交流! ---------- 一.面向对象概述 1.面向对象:是一个很抽象的概念,它相对面向过程而言,是一种程序设计的思想. 2.面向对 ...

  10. BZOJ 1816 扑克牌

    WA的我怀疑人生.. 发现原来是循环中间就要break掉,不然爆int. 总感觉这题可以直接构造啊.. #include<iostream> #include<cstdio> ...