HDU 3836&&HDU2767 强连通

来源:互联网 发布:淘宝采集软件哪个好 编辑:程序博客网 时间:2024/04/27 23:59

 至少加几条边让整个图变成强连通

入度为零的根节点数
出度为零的子节点数
取最大值

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;#include<vector>int min(int a,int b){return a>b?b:a;}int max(int a, int b){return a>b?a:b;}#define N 20100  //N为最大点数  #define M 150000  //M为最大边数  int n, m;//n m 为点数和边数  struct Edge{      int from, to, nex;      bool sign;//是否为桥  }edge[M<<1];  int head[N], edgenum;  void add(int u, int v){//边的起点和终点      Edge E={u, v, head[u], false};      edge[edgenum] = E;      head[u] = edgenum++;  }  int DFN[N], Low[N], Stack[N], top, Time; //Low[u]是点集{u点及以u点为根的子树} 中(所有反向弧)能指向的(离根最近的祖先v) 的DFN[v]值(即v点时间戳)  int taj;//连通分支标号,从1开始  int Belong[N];//Belong[i] 表示i点属于的连通分支  bool Instack[N];  vector<int> bcc[N]; //标号从1开始  void tarjan(int u ,int fa){    int i;    DFN[u] = Low[u] = ++ Time ;        Stack[top ++ ] = u ;        Instack[u] = 1 ;       for ( i = head[u] ; ~i ; i = edge[i].nex ){            int v = edge[i].to;            if(DFN[v] == -1)          {                tarjan(v , u);                Low[u] = min(Low[u] ,Low[v]) ;              if(DFN[u] < Low[v])              {                  edge[i].sign = 1;//为割桥              }          }            else if(Instack[v]){Low[u] = min(Low[u] ,DFN[v]) ;        }    }        if(Low[u] == DFN[u]){            int now;          taj ++ ; bcc[taj].clear();          do{              now = Stack[-- top] ;                Instack[now] = 0 ;               Belong [now] = taj ;              bcc[taj].push_back(now);          }while(now != u) ;      }  }  void tarjan_init(int all){      memset(DFN, -1, sizeof(DFN));      memset(Low, -1, sizeof(Low));      memset(Instack, 0, sizeof(Instack));      memset(Stack, 0, sizeof(Stack));      top = Time = taj = 0;      for(int i=1;i<=all;i++)if(DFN[i]==-1 )tarjan(i, i); //注意开始点标!!!  }  vector<int>G[N];  int du[N];  void suodian(){ int i;    memset(du, 0, sizeof(du));      for( i = 1; i <= taj; i++)G[i].clear();      for(i = 0; i < edgenum; i++){          int u = Belong[edge[i].from], v = Belong[edge[i].to];          if(u!=v){G[u].push_back(v), du[v]++;  }    }  }  void init(){memset(head, -1, sizeof(head));edgenum=0;}  int main(){while(scanf("%d%d",&n,&m)!=EOF){int i,j;init();int a,b;for( i=0;i<m;i++){scanf("%d%d",&a,&b);add(a,b);}tarjan_init(n);suodian();int sum1=0,sum2=0;if(taj==1)//已经是强连通{printf("0\n");continue;}for(i=1;i<=taj;i++)if(G[i].size()==0)sum1++;for(i=1;i<=taj;i++)if(du[i]==0)sum2++;printf("%d\n",max(sum1,sum2));}return 0;}


0 0
原创粉丝点击