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