题意:如果A是B的子集,B是B的子集,那么A,B相等,,给出一系列的关系,求还需要多少关系才能证明所有的集合都相等;
分析:典型的强联通,,需要建多少边才能使得整个图联通;
解法:1,求出所有的缩点,,2,每个缩点的初度,入度是否为零,,3,不为零的出度之和与不为零的入度之和的最大值即为所求;
当然,提醒一下,自边,重边,虽然这题应该没影响
#include <iostream> #include <cstdio> #include <cstring> #include <map> #include <vector> using namespace std ; const int N = 20000 + 11 ; const int M = 50000 + 11 ; struct Graph { struct Edge { int e ; int next ; }; Edge err[M] ; int dfn[N] , low[N] , instack[N] ; int head[N] ; bool degreein[N] ; bool degreeout[N] ; vector<int> stk ; vector<pair<int , int> > que ; int idx , color , visit_time ; int n , m ; void add_edge(int& a , int& b) { err[idx].e = b; err[idx].next = head[a] ; head[a] = idx++ ; } void addinfo() { int a , b ; while(m--) { scanf("%d%d",&a,&b); if(a == b) continue ; add_edge(a , b) ; } } void init() { memset(head , -1 , sizeof(head)) ; memset(degreein , 0 , sizeof(degreein)) ; memset(degreeout , 0 , sizeof(degreeout)) ; memset(instack , 0 , sizeof(instack)) ; idx = 1 , color = 2 , visit_time = 0 ; que.clear() ; stk.clear() ; } void dfs(int site) { stk.push_back(site) ; instack[site] = 1 ; dfn[site] = low[site] = ++visit_time ; for(int i = head[site] ; i != -1 ; i = err[i].next) { int e = err[i].e ; if(!instack[e]) { dfs(e) ; low[site] = min(low[site] , low[e]) ; }else if(instack[e] == 1){//开始这里写错了,没有if,, low[site] = min(low[site] , dfn[e]) ; } if(instack[e] > 1) { que.push_back(make_pair(site , instack[e])) ; } } if(low[site] == dfn[site]) { int tmp ; while(stk.back() != site) { tmp = stk.back() ; stk.pop_back() ; instack[tmp] = color ; } stk.pop_back() ; instack[site] = color++ ; } } void std_fun() { init() ; addinfo() ; for(int i = 1 ; i <= n ;++i) { if(instack[i] == 0) { dfs(i) ; } } while(!que.empty()) { pair<int ,int> tmp = que.back() ; que.pop_back() ; if(instack[tmp.first] != tmp.second) { degreeout[instack[tmp.first]] = true ; degreein[tmp.second] = true ; } } int a = 0 , b = 0 ; for(int i = 2 ; i < color ; ++i) { if(degreein[i] == false) ++a ; if(degreeout[i] == false) ++b ; } if(color == 3) { printf("0\n"); }else { printf("%d\n" , max(a , b)) ; } } }g ; int main() { while(scanf("%d%d",&g.n ,&g.m)==2) { g.std_fun() ; } }