2 4 0 3 2 1 2 1 3
4 2
题意:有n个命题,现已给出m次推导即由a可以推出b(根据该条件b不能推出a),问最少还需要多少次推导才可以证明n个命题之间是等价的。(等价命题:a <=> b 即 a可以推出b 且 b可以推出a。)
把每个命题虚拟成一个节点,a推导b当作一条a到b的有向边,问题就变成:在有向图中最少增加多少条边才可以使新图强连通。
思路:
将【每个强连通分支】缩成一个点,记录每个【缩点】的出度, 入度,并构造新图,然后求出所有入度为0的点数numin,求出所有出度为0的点数numuot,取最大值即可
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
#define maxn 20000 + 1000
#define maxm 50000 + 5000
using namespace std;
int n, m;
vector<int>edge[maxm];
int low[maxn], dfn[maxn];
int dfs_clock;
int Stack[maxn];
bool Instack[maxn];
int top;
int Belong[maxn] , scc_clock;
int out[maxn], in[maxn];
void init(){
for(int i = 1; i <= n; ++i)
edge[i].clear();
}
void getmap(){
scanf("%d%d", &n, &m);
while(m--){
int a, b;
scanf("%d%d", &a, &b);
edge[a].push_back(b);
}
}
void tarjan(int u, int per){
int v;
low[u] = dfn[u] = ++dfs_clock;
Stack[top++] = u;
Instack[u] = true;
for(int i = 0; i < edge[u].size(); i++){
v = edge[u][i];
if(!dfn[v]){
tarjan(v, u);
low[u] = min(low[v], low[u]);
}
else if(Instack[v]){
low[u] = min(low[u], dfn[v]);
}
}
if(dfn[u] == low[u]){
scc_clock++;
do{
v = Stack[--top];
Instack[v] = false;
Belong[v] = scc_clock;
}while(u != v);
}
}
void find(){
memset(low, 0, sizeof(low));
memset(dfn, 0, sizeof(dfn));
memset(Instack, false, sizeof(Instack));
memset(Belong, 0, sizeof(Belong));
dfs_clock = scc_clock = top = 0;
for(int i = 1; i <= n; ++i){
if(!dfn[i])
tarjan(i, i);
}
}
void suodian(){
for(int i = 1; i <= scc_clock; ++i){
in[i] = 0;
out[i] = 0;
}
for(int i = 1; i <= n; ++i){
for(int j = 0; j < edge[i].size(); ++j){
int u = Belong[i];
int v = Belong[edge[i][j]];
if(u != v){
out[u]++, in[v]++;
}
}
}
}
void solve(){
if(scc_clock == 1){
printf("0\n");
return ;
}
int numin = 0, numout = 0;
for(int i = 1; i <= scc_clock; ++i){
if(in[i] == 0) numin++;
if(out[i] == 0) numout++;
}
//printf("%d\n",scc_clock);
printf("%d\n", max(numin, numout));
}
int main (){
int T;
scanf("%d", &T);
while(T--){
init();
getmap();
find();
suodian();
solve();
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 2767--Proving Equivalences【scc缩点构图 && 求向图中最少增加多少条边才可以使新图强连通】
原文地址:http://blog.csdn.net/hpuhjh/article/details/47783945