zoukankan      html  css  js  c++  java
  • hdu

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

    判断给定的图是否是强连通的,并且每条边都只属于一个连通分量.

    判断强连通只需要判断缩点之后顶点数是否为1即可,

    然后在缩点的过程中,如果已经产生环,并且当前结点的父节点还有父节点,则必定有多个环,

    最后还要判断每个结点都要只属于一个联通分量,否则不符合要求.

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cmath>
      4 #include <vector>
      5 #include <cstring>
      6 #include <algorithm>
      7 #include <string>
      8 #include <set>
      9 #include <functional>
     10 #include <numeric>
     11 #include <sstream>
     12 #include <stack>
     13 #include <map>
     14 #include <queue>
     15 
     16 #define CL(arr, val)    memset(arr, val, sizeof(arr))
     17 
     18 #define ll long long
     19 #define inf 0x7f7f7f7f
     20 #define lc l,m,rt<<1
     21 #define rc m + 1,r,rt<<1|1
     22 #define pi acos(-1.0)
     23 
     24 #define L(x)    (x) << 1
     25 #define R(x)    (x) << 1 | 1
     26 #define MID(l, r)   (l + r) >> 1
     27 #define Min(x, y)   (x) < (y) ? (x) : (y)
     28 #define Max(x, y)   (x) < (y) ? (y) : (x)
     29 #define E(x)        (1 << (x))
     30 #define iabs(x)     (x) < 0 ? -(x) : (x)
     31 #define OUT(x)  printf("%I64d
    ", x)
     32 #define lowbit(x)   (x)&(-x)
     33 #define Read()  freopen("a.txt", "r", stdin)
     34 #define Write() freopen("dout.txt", "w", stdout);
     35 
     36 using namespace std;
     37 #define N 20100
     38 //N为最大点数
     39 #define M 50100
     40 //M为最大边数
     41 int n, m;//n m 为点数和边数
     42 
     43 struct Edge{
     44     int from, to, nex;
     45     bool sign;//是否为桥
     46 }edge[M<<1];
     47 int head[N], edgenum;
     48 void add(int u, int v){//边的起点和终点
     49     Edge E={u, v, head[u], false};
     50     edge[edgenum] = E;
     51     head[u] = edgenum++;
     52 }
     53 //DNF[i]表示遍历到第i点时,是第几次dfs
     54 //Low[u] 表示 以u点为父节点的 子树 能连接到 [栈中] 最上端的点 的DFN值(换句话说,是最小的DFN,因为最上端的DFN是最小的嘛)
     55 int DFN[N], Low[N], Stack[N], top, Time; //Low[u]是点集{u点及以u点为根的子树} 中(所有反向弧)能指向的(离根最近的祖先v) 的DFN[v]值(即v点时间戳)
     56 int taj;//连通分支标号,从1开始
     57 int Belong[N];//Belong[i] 表示i点属于的连通分支
     58 bool Instack[N],flag;
     59 vector<int> bcc[N]; //标号从1开始
     60 
     61 void tarjan(int u ,int fa){
     62     DFN[u] = Low[u] = ++ Time ;
     63     Stack[top ++ ] = u ;
     64     Instack[u] = 1 ;
     65 
     66     for (int i = head[u] ; ~i ; i = edge[i].nex ){
     67         int v = edge[i].to ;
     68         if(DFN[v] == -1)
     69         {
     70             tarjan(v , u) ;
     71             Low[u] = min(Low[u] ,Low[v]) ;
     72             if(DFN[u] < Low[v])
     73             {
     74                 edge[i].sign = 1;//为割桥
     75             }
     76         }
     77         else if(Instack[v])
     78         {
     79             Low[u] = min(Low[u] ,DFN[v]) ;
     80             if(DFN[v]!=Low[v]) flag=1; //父节点还不是根节点
     81         }
     82     }
     83     if(Low[u] == DFN[u]){
     84         int now;
     85         taj ++ ; bcc[taj].clear();
     86         do{
     87             now = Stack[-- top] ;
     88             Instack[now] = 0 ;
     89             if(Belong[now]!=-1) flag=1; //每个节点都要只属于一个联通分量
     90             Belong [now] = taj ;
     91             bcc[taj].push_back(now);
     92         }while(now != u) ;
     93     }
     94 }
     95 
     96 void tarjan_init(int all){
     97     memset(DFN, -1, sizeof(DFN));
     98     memset(Instack, 0, sizeof(Instack));
     99     memset(Belong,-1,sizeof(Belong));
    100     top = Time = taj = 0;
    101     for(int i=1;i<=all;i++)if(DFN[i]==-1 )tarjan(i, i); //注意开始点标!!!
    102 }
    103 vector<int>G[N];
    104 int du[N];
    105 void suodian(){
    106     memset(du, 0, sizeof(du));
    107     for(int i = 1; i <= taj; i++)G[i].clear();
    108     for(int i = 0; i < edgenum; i++){
    109         int u = Belong[edge[i].from], v = Belong[edge[i].to];
    110         if(u!=v)
    111         {
    112             G[u].push_back(v), du[v]++;
    113            // printf("%d %d
    ",u,v);
    114         }
    115     }
    116 }
    117 void init(){memset(head, -1, sizeof(head)); edgenum=0;}
    118 int main()
    119 {
    120     //Read();
    121     int t,a,b;
    122     scanf("%d",&t);
    123     while(t--)
    124     {
    125         scanf("%d",&n);
    126         init();
    127         flag=0;
    128         while(1)
    129         {
    130             scanf("%d%d",&a,&b);
    131             if(a==0&&b==0) break;
    132             add(a+1,b+1);
    133         }
    134         tarjan_init(n);
    135         suodian();
    136 
    137         if(taj==1&&flag==0) puts("YES");
    138         else puts("NO");
    139     }
    140     return 0;
    141 }
  • 相关阅读:
    Java实现 蓝桥杯 算法提高 小X的购物计划
    Java实现 蓝桥杯 算法提高 小X的购物计划
    Java实现 第十一届 蓝桥杯 (高职专科组)省内模拟赛
    Java实现 第十一届 蓝桥杯 (高职专科组)省内模拟赛
    Java实现 第十一届 蓝桥杯 (高职专科组)省内模拟赛
    Java 第十一届 蓝桥杯 省模拟赛 小明的城堡
    Java 第十一届 蓝桥杯 省模拟赛 小明的城堡
    Java 第十一届 蓝桥杯 省模拟赛 小明的城堡
    129. Sum Root to Leaf Numbers
    117. Populating Next Right Pointers in Each Node II
  • 原文地址:https://www.cnblogs.com/nowandforever/p/4731071.html
Copyright © 2011-2022 走看看