• POJ 2762 (弱连通)强连通+缩点+拓扑排序


    题意:给出T个山洞,对于每个山洞,如果任意选择两点s,e,都满足s可以到达e或者e可以到达s,则输出Yes,否则输出No。

    思路:如果两点不可达那么在拓扑排序时,该两点谁也不是谁的前驱和后继,那么在拓扑排序时定会出现至少两个度为0的点,这两个点分别是它们本身或它们的拓扑序列的前驱。如果在拓扑排序时发现有多于1个度为0的点,那么这些点必然不可达。由此推出该题为No的充分必要条件:缩点拓扑排序过程中出现至少两个度为0的点。

    思路摘自:http://happylch21.blog.163.com/blog/static/1656397592011711261518/

    (我还是刚知道弱连通这个东西。。)

    View Code
      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cstdlib>
      4 #include <iostream>
      5 
      6 #define N 1200
      7 #define M 12000
      8 
      9 using namespace std;
     10 
     11 int n,m,to[M],next[M],head[N],in[N],cnt,dfn[N],low[N],divg,t,p,stk[N],belong[N],tt;
     12 int next1[M],to1[M],head1[N],cnt1;
     13 bool fg[N],map[N][N];
     14 
     15 inline void add(int u,int v)
     16 {
     17     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;
     18 }
     19 
     20 inline void add1(int u,int v)
     21 {
     22     to1[cnt1]=v; next1[cnt1]=head1[u]; head1[u]=cnt1++;
     23 }
     24 
     25 void read()
     26 {
     27     memset(head,-1,sizeof head);cnt=0;
     28     memset(dfn,0,sizeof dfn);
     29     memset(fg,0,sizeof fg);
     30     t=0; divg=0; p=0;
     31     scanf("%d%d",&n,&m);
     32     for(int i=1,a,b;i<=m;i++)
     33     {
     34         scanf("%d%d",&a,&b);
     35         add(a,b);
     36     }
     37 }
     38 
     39 void dfs(int u)
     40 {
     41     t++;
     42     dfn[u]=low[u]=t;
     43     stk[++p]=u; fg[u]=true;
     44     for(int i=head[u];~i;i=next[i])
     45     {
     46         if(!dfn[to[i]])
     47         {
     48             dfs(to[i]);
     49             low[u]=min(low[u],low[to[i]]);
     50         }
     51         else if(fg[to[i]]) low[u]=min(low[u],dfn[to[i]]);
     52     }
     53     if(dfn[u]==low[u])
     54     {
     55         divg++;
     56         int tmp=-1;
     57         while(tmp!=u)
     58         {
     59             tmp=stk[p--];
     60             belong[tmp]=divg;
     61             fg[tmp]=false;
     62         }
     63     }
     64 }
     65 
     66 void rebuild()
     67 {
     68     memset(in,0,sizeof in);
     69     memset(map,0,sizeof map);
     70     memset(head1,-1,sizeof head1);cnt1=0;
     71     for(int i=1;i<=n;i++)
     72         for(int j=head[i];~j;j=next[j])
     73             if(belong[i]!=belong[to[j]]&&!map[belong[i]][belong[to[j]]])
     74             {
     75                 in[belong[to[j]]]++;
     76                 add1(belong[i],belong[to[j]]);
     77                 map[belong[i]][belong[to[j]]]=true;
     78             }
     79 }
     80 
     81 bool toposort()
     82 {
     83     int num=0,cur;
     84     for(int i=1;i<=divg;i++)
     85         if(!in[i]) cur=i,num++;
     86     if(num>1) return false;
     87     int tmp=divg;
     88     while(tmp--)
     89     {
     90         num=0;
     91         for(int i=head1[cur];~i;i=next1[i])
     92         {
     93             in[to1[i]]--;
     94             if(!in[to1[i]]) num++,cur=to1[i];
     95         }
     96         if(num>1) return false;
     97     }
     98     return true;
     99 }
    100 
    101 void go()
    102 {
    103     for(int i=1;i<=n;i++)
    104         if(!dfn[i]) dfs(i);
    105     if(divg==1)
    106     {
    107         puts("Yes");
    108         return;
    109     }
    110     
    111     
    112     rebuild();
    113     if(toposort()) puts("Yes");
    114     else puts("No");
    115 }
    116 
    117 int main()
    118 {
    119     scanf("%d",&tt);
    120     while(tt--)
    121     {
    122         read();
    123         go();
    124     }
    125     system("pause");
    126     return 0;
    127 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    Java设计模式之装饰模式
    学习Emacs系列教程(二):导航
    Android ProgressDialog 延时消失
    java设计模式装饰模式
    Java 字节流和字符流的相互转换
    emacs配置颜色主题
    Android ProgressDialog的使用
    个人管理 时间管理GTD流程图
    jQuery - 列表控件推荐
    WPF - 模板查看工具:Show Me The Template及如何查看第三方主题
  • 原文地址:https://www.cnblogs.com/proverbs/p/2710594.html
Copyright © 2020-2023  润新知