• POJ 2762 tarjan缩点+并查集+度数


    Going from u to v or from v to u?
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 15494   Accepted: 4100

    Description

    In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has n rooms, and one-way corridors connecting some rooms. Each time, Wind choose two rooms x and y, and ask one of their little sons go from one to the other. The son can either go from x to y, or from y to x. Wind promised that her tasks are all possible, but she actually doesn't know how to decide if a task is possible. To make her life easier, Jiajia decided to choose a cave in which every pair of rooms is a possible task. Given a cave, can you tell Jiajia whether Wind can randomly choose two rooms without worrying about anything?

    Input

    The first line contains a single integer T, the number of test cases. And followed T cases. 

    The first line for each case contains two integers n, m(0 < n < 1001,m < 6000), the number of rooms and corridors in the cave. The next m lines each contains two integers u and v, indicating that there is a corridor connecting room u and room v directly. 

    Output

    The output should contain T lines. Write 'Yes' if the cave has the property stated above, or 'No' otherwise.

    Sample Input

    1
    3 3
    1 2
    2 3
    3 1
    

    Sample Output

    Yes

    Source

     
    题目意思:
    给一n个点、m条边的有向图,问是否随意选两个点u和v,是否能从u到达v或者从v到达u。
     
    思路:
    如果弱连通分量有多个,那么肯定是不可到达的,所以用并查集处理一下。
    强连通分量内部随意两个点是互相到达的,不互相到达的点在强连通分量之间,所以先用tarjan强连通分量缩点,若入度为0的个数>=2||出度为0的个数>=2那么也是不可到达的。
    各种条件判断一下即可。
     
    代码:
      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <iostream>
      5 #include <vector>
      6 #include <queue>
      7 #include <cmath>
      8 #include <set>
      9 #include <stack>
     10 using namespace std;
     11 
     12 #define N 1005
     13 
     14 int max(int x,int y){return x>y?x:y;}
     15 int min(int x,int y){return x<y?x:y;}
     16 int abs(int x,int y){return x<0?-x:x;}
     17 
     18 int n, m;
     19 bool in[N];
     20 int suo[N];
     21 int cnt;
     22 vector<int>ve[N];
     23 int dfn[N], low[N], Time;
     24 stack<int>st;
     25 int father[N];
     26 
     27 int findroot(int u){
     28     if(father[u]!=u) father[u]=findroot(father[u]);
     29     return father[u];
     30 }
     31 
     32 void tarjan(int u){
     33     dfn[u]=low[u]=Time++;
     34     st.push(u);in[u]=true;
     35     int i, j, k;
     36     for(i=0;i<ve[u].size();i++){
     37         int v=ve[u][i];
     38         if(dfn[v]==-1){
     39             tarjan(v);
     40             low[u]=min(low[u],low[v]);
     41         }
     42         else if(in[v]) low[u]=min(low[u],dfn[v]);
     43     }
     44     if(dfn[u]==low[u]){
     45         while(1){
     46             int x=st.top();
     47             suo[x]=cnt;
     48             in[x]=false;
     49             st.pop();
     50             if(x==u||st.empty()) break;
     51         }
     52         cnt++;
     53     }
     54 }
     55 
     56 main()
     57 {
     58     int i, j, k, u, v;
     59     int t;
     60     cin>>t;
     61     
     62     while(t--){
     63         scanf("%d %d",&n,&m);
     64         for(i=0;i<=n;i++) ve[i].clear();
     65         for(i=0;i<m;i++){
     66             scanf("%d %d",&u,&v);
     67             ve[u].push_back(v);
     68         }
     69         Time=cnt=1;
     70         memset(dfn,-1,sizeof(dfn));
     71         while(!st.empty()) st.pop();
     72         memset(in,false,sizeof(in));
     73         for(i=1;i<=n;i++){
     74             if(dfn[i]==-1){
     75                 tarjan(i);
     76             }
     77         }
     78         int inn[N], out[N];
     79         memset(inn,0,sizeof(inn));
     80         memset(out,0,sizeof(out));
     81         for(i=1;i<=n;i++) father[i]=i;
     82         for(i=1;i<=n;i++){
     83             for(j=0;j<ve[i].size();j++){
     84                 int u=suo[i], v=suo[ve[i][j]];
     85                 if(u!=v){
     86                     father[findroot(v)]=findroot(u);
     87                     inn[v]++;
     88                     out[u]++;
     89                 }
     90             }
     91         }
     92         
     93         int num=0;
     94         for(i=1;i<cnt;i++){
     95             if(father[i]==i) num++;
     96         }
     97         if(num>1) {
     98             printf("No
    ");continue;
     99         }
    100     
    101         int n1, n2;
    102         n1=n2=0;
    103         for(i=1;i<cnt;i++){
    104             if(!inn[i]) n1++;
    105             if(!out[i]) n2++;
    106         }
    107         if(n1>1||n2>1) printf("No
    ");
    108         else printf("Yes
    ");
    109     }
    110 }
  • 相关阅读:
    7、单向一对多的关联关系(1的一方有n的一方的集合属性,n的一方却没有1的一方的引用)
    6、JPA_映射单向多对一的关联关系(n的一方有1的引用,1的一方没有n的集合属性)
    解决ubuntu的screen已经处于Attached状态,无法再打开窗口
    关于.ssh出错,无法从远程git仓库拉代码
    给程序添加git commit信息
    ubuntu服务器常用命令
    uint128_t 添加 c++ 重载类型强制转换
    Visual Studio 查看宏展开
    EOS dice移到1.8版本的修改汇总
    ubuntu 添加字体
  • 原文地址:https://www.cnblogs.com/qq1012662902/p/4637805.html
Copyright © 2020-2023  润新知