zoukankan      html  css  js  c++  java
  • POJ 2762 Going from u to v or from v to u? (强连通分量缩点+拓扑排序)

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

    题意是 有t组样例,n个点m条有向边,取任意两个点u和v,问u能不能到v 或者v能不能到u,要是可以就输出Yes,否则输出No。注意一点,条件是或者!所以不是判断双连通图的问题。

    我一开始没看到'or'这个条件,所以直接tarjan判断是否只有一个强连通分量,果断WA。

    所以需要给原图缩点,用tarjan把图变成一个有向无环图,要是只有一个scc,那就直接输出Yes。那接下来讨论多个scc,要是新图中有两个及以上的点的入度为0,则这些点都不能相互到达,所以输出No,所以我们找到唯一一个入度为0的点作为root,然后从这个点来拓扑排序,出队入队的过程肯定是一进一出的,所以根据过程来判断是否输出Yes和No。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <vector>
      5 #include <queue>
      6 using namespace std;
      7 const int MAXN = 1005;
      8 struct data {
      9     int next , to;
     10 }edge[MAXN * 6];
     11 int head[MAXN] , st[MAXN] , low[MAXN] , dfn[MAXN] , block[MAXN] , du[MAXN];
     12 int top , ord , sccnum , cont;
     13 bool instack[MAXN];
     14 vector <int> G[MAXN];
     15 
     16 inline void add(int u , int v) {
     17     edge[cont].next = head[u];
     18     edge[cont].to = v;
     19     head[u] = cont++;
     20 }
     21 
     22 void init() {
     23     memset(head , -1 , sizeof(head));
     24     memset(dfn , 0 , sizeof(dfn));
     25     memset(du , 0 , sizeof(du));
     26     memset(instack , false , sizeof(instack));
     27     top = sccnum = ord = cont = 0;
     28 }
     29 
     30 void tarjan(int u) {
     31     low[u] = dfn[u] = ++ord;
     32     st[++top] = u;
     33     instack[u] = true;
     34     for(int i = head[u] ; ~i ; i = edge[i].next) {
     35         int v = edge[i].to;
     36         if(!dfn[v]) {
     37             tarjan(v);
     38             low[u] = min(low[u] , low[v]);
     39         }
     40         else if(instack[v]) {
     41             low[u] = min(low[u] , low[v]);
     42         }
     43     }
     44     if(low[u] == dfn[u]) {
     45         int v;
     46         sccnum++;
     47         do {
     48             v = st[top--];
     49             instack[v] = false;
     50             block[v] = sccnum;
     51         }while(u != v);
     52     }
     53 }
     54 
     55 void top_sort() {
     56     queue <int> que;
     57     while(!que.empty()) {
     58         que.pop();
     59     }
     60     cont = 0;
     61     for(int i = 1 ; i <= sccnum ; i++) {
     62         if(!du[i]) {
     63             que.push(i);
     64             cont++;
     65         }
     66     }
     67     if(cont > 1) {
     68         printf("No
    ");
     69         return ;
     70     }
     71     while(!que.empty()) {
     72         int temp = que.front() , cnt = 0;
     73         que.pop();
     74         for(int i = 0 ; i < G[temp].size() ; i++) {
     75             du[G[temp][i]]--;
     76             if(!du[G[temp][i]]) {
     77                 cnt++;
     78                 cont++;
     79                 que.push(G[temp][i]);
     80             }
     81         }
     82         if(cnt > 1) {
     83             printf("No
    ");
     84             return ;
     85         }
     86     }
     87     if(cont != sccnum) {
     88         printf("No
    ");
     89     }
     90     else {
     91         printf("Yes
    ");
     92     }
     93 }
     94 
     95 int main()
     96 {
     97     int t , n , m , u , v;
     98     scanf("%d" , &t);
     99     while(t--) {
    100         scanf("%d %d" , &n , &m);
    101         init();
    102         for(int i = 0 ; i < m ; i++) {
    103             scanf("%d %d" , &u , &v);
    104             add(u , v);
    105         }
    106         for(int i = 1 ; i <= n ; i++) {
    107             G[i].clear();
    108             if(!dfn[i])
    109                 tarjan(i);
    110         }
    111         if(sccnum == 1) {
    112             printf("Yes
    ");
    113             continue;
    114         }
    115         for(int u = 1 ; u <= n ; u++) {
    116             for(int i = head[u] ; ~i ; i = edge[i].next) {
    117                 int v = edge[i].to;
    118                 if(block[u] != block[v]) {
    119                     du[block[v]]++;
    120                     G[block[u]].push_back(block[v]);
    121                 }
    122             }
    123         }
    124         top_sort();
    125     }
    126 }
  • 相关阅读:
    odoo 的各种domain
    odoo search之时间搜索,时间段查询
    git 修改远程仓库地址
    Windows 挂起进程
    结构体 偏移量 (size_t)&(((s *)0)->m) , list相关
    Data Flow Diagram with Examples
    Windows环境,获取当前线程的ID,GetCurrentThreadId
    获取 保存 系统信息 [Windows]
    notepad正则删除关键词所在行
    文件或文件夹改变后,发信号让系统刷新
  • 原文地址:https://www.cnblogs.com/Recoder/p/5272990.html
Copyright © 2011-2022 走看看