HDU 3836 Equivalent Sets 强连通分量

来源:互联网 发布:禁毒网络知识竞赛答案 编辑:程序博客网 时间:2024/05/01 06:32

题意:让所有点强连通需要最少连多少条边?

思路:缩点,求出每个强连通分量的入度和出度,如果强连通分量的入度为0,则incnt++,如果强连通分量的出度为0,则outcnt++,取max(incnt,outcnt)就是答案。因为一个强连通的图中,每个点的入度和出度都是1的。所有最多只要连max(incnt,outcnt)条线,因为可以将出度为0的点连上入度为0的点。

http://acm.hdu.edu.cn/showproblem.php?pid=3836

/*********************************************    Problem : HDU 3836    Author  : NMfloat    InkTime (c) NM . All Rights Reserved .********************************************/#include <map>#include <set>#include <queue>#include <cmath>#include <ctime>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>#define rep(i,a,b)  for(int i = a ; i <= b ; i ++)#define rrep(i,a,b) for(int i = b ; i >= a ; i --)#define repE(p,u) for(Edge * p = G[u].first ; p ; p = p -> next)#define cls(a,x)   memset(a,x,sizeof(a))using namespace std;typedef long long LL;const int MOD = 1e9+7;const int INF = 0x3f3f3f3f;const int MAXN = 2e4+5;const int MAXE = 5e4+5;struct Edge {    int to;    Edge * next ;}E[MAXE], * EE;struct Gragh {    Edge * first ;}G[MAXN];int T,n,m;int Stack[MAXN] ; bool InStack[MAXN];int dfn[MAXN] , low[MAXN] , num[MAXN] , belong[MAXN];int idx,top,scc;void addedge(int u,int v) {    EE->to = v ; EE->next = G[u].first ; G[u].first = EE ++;} void init() {    EE = E; idx = top = scc = 0;    cls(G,0); cls(dfn,0); cls(InStack,0);}void tarjan(int u) {    int v;    dfn[u] = low[u] = ++idx;    Stack[top++] = u;    InStack[u] = true;    repE(p,u) {        v = p -> to;        if(!dfn[v]) {            tarjan(v);            if(low[u] > low[v]) low[u] = low[v];        }        else if(InStack[v] && low[u] > dfn[v])             low[u] = dfn[v];    }    if(low[u] == dfn[u]) {        scc ++;        do {            v = Stack[--top];            InStack[v] = false;            belong[v] = scc;            num[scc] ++;        } while(v != u) ;    }}int X[MAXE];int Y[MAXE];int indegree[MAXN];int outdegree[MAXN];void input() {    int u,v;    rep(i,1,m) {        scanf("%d %d",&u,&v);        X[i] = u; Y[i] = v;        addedge(u,v);    }}void solve() {    rep(i,1,n) {        if(!dfn[i]) tarjan(i);          }    if(scc == 1) {        puts("0");    }    else {        int incnt = 0 , outcnt = 0;        cls(indegree,0); cls(outdegree,0);        rep(i,1,m) {            if(belong[X[i]] != belong[Y[i]]) {                indegree[belong[Y[i]]] ++;                outdegree[belong[X[i]]] ++;            }        }        rep(i,1,scc) {            if(indegree[i] == 0) incnt ++;            if(outdegree[i] == 0) outcnt ++;        }        printf("%d\n",max(incnt,outcnt));    }}   int main(void) {    //freopen("a.in","r",stdin);    //scanf("%d",&T);    while(~scanf("%d %d",&n,&m)) {        init();        input();        solve();    }    return 0;}
0 0