• POJ 2762 强连通分量中存在单相连通边 【tarjan+toposort+缩点】.cpp


    题意:

      给出一些房间之间的关系

      问任意两个房间是否存在一条互通的路径..即单相连通..

     

      输入:

      给出T表示有T组数据

      每组数据给出n m 表示n个房间 m个关系

      接下来m行..每行给出a b 表示a房间 和 b房间之间是连通的..

     

      如果任意两个房间之间存在单相连通..则输出yes 否则 no

     

    思路:

      先用tarjan算法求出每个强连通分量..然后对每一个进行染色..

      然后建图..拓扑排序..

      如果排序不唯一..就是有超过两个点是有0个初度的..

      这代表其中有两个房间是不相连的..

     

    Tips:

      点太多或者边太多的情况下..

      就要用前向星建图了..

    Code:

    View Code
      1 #include <stdio.h>
      2 #include <cstring>
      3 #include <algorithm>
      4 using namespace std;
      5 #define clr(x) memset(x, 0, sizeof(x))
      6 const int INF = 0x1f1f1f1f;
      7 const int MAXN = 1010;
      8 
      9 int n, m;
     10 
     11 struct Edge
     12 {
     13     int to;
     14     int next;
     15 }edge[1000010], edge2[1000010];
     16 int head[MAXN], head2[MAXN];
     17 int tot, tot2;
     18 
     19 void add(int s, int u)
     20 {
     21     edge[tot].to = u;
     22     edge[tot].next = head[s];
     23     head[s] = tot++;
     24 }
     25 
     26 void add2(int s, int u)
     27 {
     28     edge2[tot2].to = u;
     29     edge2[tot2].next = head2[s];
     30     head2[s] = tot2++;
     31 }
     32 
     33 int ti, top, cnt;
     34 int dfn[MAXN], low[MAXN], ins[MAXN];
     35 int col[MAXN], sta[MAXN];
     36 
     37 void tarjan(int u)
     38 {
     39     int i, k;
     40     dfn[u] = low[u] = ++ti;
     41     sta[++top] = u;
     42     ins[u] = 1;
     43     for(i = head[u]; i != -1; i = edge[i].next) {
     44         k = edge[i].to;
     45         if(dfn[k] == 0) {
     46             tarjan(k);
     47             low[u] = min(low[u], low[k]);
     48         }
     49         else if(ins[k]) {
     50             low[u] = min(low[u], dfn[k]);
     51         }
     52     }
     53 
     54     if(dfn[u] == low[u]) {
     55         ++cnt;
     56         do
     57         {
     58             k = sta[top--];
     59             col[k] = cnt;
     60             ins[k] = 0;
     61         }while(k != u);
     62     }
     63 }
     64 
     65 void solve_ta()
     66 {
     67     ti = top = cnt = 0;
     68     clr(dfn), clr(ins);
     69     for(int i = 1; i <= n; ++i)
     70     if(!dfn[i])
     71         tarjan(i);
     72 }
     73 
     74 int ind[MAXN];
     75 int q[MAXN];
     76 int v[MAXN];
     77 int f1, f2, num;
     78 
     79 void make_G()
     80 {
     81     int i, j, k;
     82     tot2 = 0;
     83     memset(head2, 0xff, sizeof(head2));
     84 
     85     solve_ta();
     86     for(i = 1; i <= n; ++i)
     87         for(j = head[i]; j != -1; j = edge[j].next) {
     88             k = edge[j].to;
     89             if(col[i] != col[k]) {
     90                 add2(col[i], col[k]);
     91                 ind[col[k]]++;
     92             }
     93         }
     94 }
     95 
     96 void toposort()
     97 {
     98     int front = 0, rear = 0;
     99     int i, k;
    100     f1 = 1, f2 = 0;
    101     clr(ind);
    102     make_G();
    103 
    104     for(i = 1; i <= cnt; i++)
    105         if(ind[i] == 0)
    106             q[rear++] = i;
    107     if(rear > 1)
    108         f1 = -1;
    109     num = 0;
    110     while(front < rear) {
    111         int x = q[front++];
    112         int tt = 0;
    113         num++;
    114         for(i = head2[x]; i!=-1; i = edge2[i].next) {
    115             k = edge2[i].to;
    116             ind[k]--;
    117             if(ind[k] == 0) {
    118                 q[rear++] = k;
    119                 tt++;
    120             }
    121         }
    122         if(tt > 1)
    123             f2 = -1;
    124     }
    125 }
    126 int main()
    127 {
    128     int i, j, k;
    129     int T;
    130     int a, b;
    131     bool flag;
    132     while(scanf("%d", &T) != EOF)
    133     while(T--)
    134     {
    135         tot = 0;
    136         memset(head, 0xff, sizeof(head));
    137         flag = true;
    138 
    139         scanf("%d %d", &n, &m);
    140         while(m--) {
    141             scanf("%d %d", &a, &b);
    142             add(a, b);
    143         }
    144 
    145         toposort();
    146         if(f1 == -1 || f2 == -1 || num != cnt) flag = false;
    147 
    148         if(flag) puts("Yes");
    149         else puts("No");
    150     }
    151     return 0;
    152 }

     

    题目链接:http://poj.org/problem?id=2762

  • 相关阅读:
    关闭Axapta
    使用API操纵文件
    调用数据源里面的方法
    Axapta进度条应用
    过滤Form的数据源
    使用系统自动产生编号
    获取表中的所有字段
    打开浏览器URL
    报表的一些常用选项
    .NET中访问Oracle数据库链接:ORA02041: client database did not begin a transaction 问题的处理。
  • 原文地址:https://www.cnblogs.com/Griselda/p/2711084.html
Copyright © 2020-2023  润新知