给定n个命题之间的已经证明的关系如 a b表示已经证明蕴含式a→b,要求还需要再作多少次证明使得所有的命题都是等价的.将每个命题看成一个点,已经证明的命题之间连一条边,问题转化为添加多少条单向边使得图成为一个强连通分量.

先求出所有的强连通分量,然后缩点构成一个SCC图,统计其中入度为0的点个数a,以及出度为0的点的个数b,max(a,b)就是需要再作的证明.注意当图一开始就是强连通时,不需要作出证明了.

来自刘汝佳算法训练指南代码:

#include <iostream>
#include <sstream>
#include <cstdio>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <string>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#define esp 1e-6
#define pi acos(-1.0)
#define pb push_back
#define mp(a, b) make_pair((a), (b))
#define in freopen("in.txt", "r", stdin);
#define out freopen("out.txt", "w", stdout);
#define print(a) printf("%d\n",(a));
#define bug puts("********))))))");
#define stop system("pause");
#define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
#define pragma comment(linker, "/STACK:102400000, 102400000")
#define inf 0x0f0f0f0f using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int, int> pii;
typedef vector<pii,int> VII;
typedef vector<int>:: iterator IT;
const int maxn = 22222;
int pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt;
int in0[maxn], out0[maxn];
VI g[maxn];
stack<int> S;
void dfs(int u)
{
S.push(u);
lowlink[u] = pre[u] = ++dfs_clock;
for(int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
if(!pre[v])
{
dfs(v);
lowlink[u] = min(lowlink[u], lowlink[v]);
}
else if(!sccno[v])
{
lowlink[u] = min(lowlink[u], pre[v]);
}
}
if(lowlink[u] == pre[u])
{
scc_cnt++;
for(;;)
{
int x = S.top();
S.pop();
sccno[x] = scc_cnt;
if(x == u) break;
}
}
}
void find_scc(int n)
{
memset(pre, 0, sizeof(pre));
memset(sccno, 0, sizeof(sccno));
dfs_clock = scc_cnt = 0;
for(int i = 0; i < n; i++)
if(!pre[i]) dfs(i);
}
int main(void)
{in
int n, m;
int T;
for(int t = scanf("%d", &T); t <= T; t++)
{
for(int i = 0; i < maxn; i++)
g[i].clear();
memset(in0, 1, sizeof(in0));
memset(out0, 1, sizeof(out0));
scanf("%d%d", &n, &m);
while(m--)
{
int u, v;
scanf("%d%d", &u, &v);
u--, v--;
g[u].pb(v);
}
find_scc(n);
for(int u = 0; u < n; u++)
for(int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
if(sccno[v] != sccno[u])
in0[sccno[v]] = out0[sccno[u]] = 0;
}
int a = 0, b= 0;
for(int i = 1; i <= scc_cnt; i++)
{
if(in0[i]) a++;
if(out0[i]) b++;
}
int ans = 0;
if(scc_cnt != 1) ans = max(a, b);
printf("%d\n",ans);
}
return 0;
}

UVALive - 4287 Proving Equivalences的更多相关文章

  1. UVALive - 4287 - Proving Equivalences(强连通分量)

    Problem   UVALive - 4287 - Proving Equivalences Time Limit: 3000 mSec Problem Description Input Outp ...

  2. UVALive 4287 Proving Equivalences(缩点)

    等价性问题,给出的样例为 a->b的形式,问要实现全部等价(即任意两个可以互相推出),至少要加多少个形如 a->b的条件. 容易想到用强连通缩点,把已经实现等价的子图缩掉,最后剩余DAG. ...

  3. UvaLive 4287 Proving Equivalences 强连通缩点

    原题链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

  4. UVALIVE 4287 Proving Equivalences (强连通分量+缩点)

    题意:给定一个图,问至少加入多少条边能够使这个图强连通. 思路:首先求出这个图的强连通分量.然后把每个强连通分量缩成一个点.那么这个图变成了一个DAG,求出全部点的入度和出度,由于强连通图中每个节点的 ...

  5. UVALive 4287 Proving Equivalence (强连通分量)

    把证明的关系看出一张图,最终就是要所有的点都在至少一个环中.环的判断和度数有关. 用tarjan找强连通分量,在一个强连通分量点已经等价缩点以后形成一个DAG,计算入度为0的点数a, 出度为0的b,取 ...

  6. 训练指南 UVALive - 4287 (强连通分量+缩点)

    layout: post title: 训练指南 UVALive - 4287 (强连通分量+缩点) author: "luowentaoaa" catalog: true mat ...

  7. hdu 2767 Proving Equivalences

    Proving Equivalences 题意:输入一个有向图(强连通图就是定义在有向图上的),有n(1 ≤ n ≤ 20000)个节点和m(0 ≤ m ≤ 50000)条有向边:问添加几条边可使图变 ...

  8. hdoj 2767 Proving Equivalences【求scc&&缩点】【求最少添加多少条边使这个图成为一个scc】

    Proving Equivalences Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  9. Proving Equivalences(加多少边使其强联通)

    Proving Equivalences Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

随机推荐

  1. eclipse怎么切换SVN的用户

    在用eclipse的时候会经常用到SVN来进行代码的版本控制,为了方便起见,我们会保存密码,从此之后就不会再出现输入或者修改用户名和密码的地方了,这时候想切换用户怎么办,在本地操作的一种方法是删除SV ...

  2. iOS夯实:ARC时代的内存管理

    iOS夯实:ARC时代的内存管理 文章转自 ARC时代的内存管理 什么是ARC Automatic Reference Counting (ARC) is a compiler feature tha ...

  3. iOS启动图片适配问题

    Portrait 是竖屏 top home button Landscape是横屏 left home button retina 要求640x1136pixels, 在右边的Image属性 Expe ...

  4. asp:手机扫描二维码跳转手机版

    如果想手机扫描用pc版网站生成的二维码跳转到对应的手机版的话,请在pc端的首页的<head></head>标签里面加入下面内容:   <script src=" ...

  5. 一种c#深拷贝方式完胜java深拷贝(实现上的对比)

    楼主是一名asp.net攻城狮,最近经常跑java组客串帮忙开发,所以最近对java的一些基础知识特别上心.却遇到需要将一个对象深拷贝出来做其他事情,而原对象保持原有状态的情况.(实在是不想自己new ...

  6. JAVA时钟

    效果图如下: //简单动态时钟程序,以图形和数字两种方式来显示当前时间 import javax.swing.*; import java.awt.event.*; import java.awt.* ...

  7. 安装ipython notebook

    从http://cs231n.github.io/assignments2016/assignment1/开始说起,因为要学习cs231n课程,需要安装ipython notebook,原本电脑中安装 ...

  8. Headfirst设计模式的C++实现——迭代器(Iterator)改良版

    iterator.h #ifndef _ITERATOR_H_ #define _ITERATOR_H_ class Iterator { public: ; ; }; #endif menu.h # ...

  9. shell环境

    1 引言 一个进程运行在shell环境中,理解进程运行的环境是十分重要的.环境影响着进程的行为,利用环境提供的便利,可以极大地提高开发效率.本节深入讨论shell中与进程有关的环境问题,包括命令行参数 ...

  10. 排序算法ONE:选择排序SelectSort

    /** *选择排序: * 对冒泡排序的一个改进 * 进行一趟排序时,不用每一次都交换,只需要把最大的标示记下 * 然后再进行一次交换 */ public class SelectSort { /** ...