zoukankan      html  css  js  c++  java
  • [vios1023]维多利亚的舞会3<强联通分量tarjan>

    题目链接:https://vijos.org/p/1023

    最近在练强联通分量,当然学的是tarjan算法

    而这一道题虽然打着难度为3,且是tarjan算法的裸题出没在vijos里面

    但其实并不是纯粹只需要tarjan求有几个强联通就可以过的(我以为这是所谓的裸题)

    其实这题还需要对每一个强联通缩点,可能被所谓裸题误导的OIer们看不破这个

    毕竟,这个样例数据也是坑啊,样例数据都可以说是无向图了,哪里还是什么有向图

    所以样例数据不是万能的,但是没过样例数据是万万不能的

    至于为什么缩点我们来想一想,这张图中,怎么才满足可以被通知到

    是在一个强联通分量里面?还是有一条边相连?还是有别的人指向他?

    当然可以想到是有人指向他,这样就可以排除求出强联通分量个数的方法。。

    不过我们可以确认的是,在一个强联通分量的点,只需要一个点就可以把这个强联通分量通知完,然后我们就可以判断任意两个强联通分量有没有可能有联系,也就是刚刚提到的有没有指向这个强联通分量的其他分量,也就是有没有入度。如果有入度,我们就可以把这个强联通分量与另一个合并,也就是这两个分量只要一个人就可以通知完。由于在这里理解成强联通分量会有些麻烦,所以就是所谓的缩点,把这个强联通分量看成一个点再来找边和入度

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<cmath>
     5 #include<queue>
     6 #include<stack>
     7 #include<algorithm>
     8 #include<cstdlib>
     9 #define maxn 205
    10 using namespace std;
    11 
    12 struct node{
    13     int u,v,w,nxt;
    14 }e[maxn*maxn];
    15 
    16 int head[maxn],dfn[maxn],low[maxn],belong[maxn];
    17 int num,tot,n,m,k,ans,in[maxn],cnt;
    18 stack<int >s;
    19 
    20 void adde(int u,int v){
    21     e[++tot].u=u;
    22     e[tot].v=v;
    23     e[tot].nxt=head[u];
    24     head[u]=tot;
    25 }
    26 
    27 void tarjan(int u){
    28     num++;
    29     dfn[u]=low[u]=num;
    30     s.push(u);
    31     for(int i=head[u];i!=-1;i=e[i].nxt){
    32         int v=e[i].v;
    33         if(dfn[v]==0){
    34             tarjan(v);
    35             low[u]=min(low[u],low[v]);
    36         }else{
    37             if(!belong[v])low[u]=min(low[u],dfn[v]);
    38         }
    39     }
    40     if(dfn[u]==low[u]){
    41         ans++;
    42         belong[u]=ans;
    43         while(s.top()!=u){
    44             belong[s.top()]=ans;
    45             s.pop();    
    46         }s.pop();
    47     }
    48 }
    49 
    50 int main(){
    51     memset(head,-1,sizeof(head));
    52     scanf("%d",&n);
    53     for(int i=1;i<=n;i++){
    54         int a;scanf("%d",&a);
    55         while(a!=0){
    56             adde(i,a);scanf("%d",&a);}
    57     }
    58     for(int i=1;i<=n;i++){
    59         if(dfn[i]==0)tarjan(i);
    60     }
    61     for(int i=1;i<=tot;i++){
    62         int u=e[i].u,v=e[i].v;
    63         if(belong[u]!=belong[v]){
    64             in[belong[v]]++;
    65         }
    66     }
    67     for(int i=1;i<=ans;i++){
    68         if(!in[i])cnt++;
    69     }
    70     printf("%d",cnt);
    71 }
    View Code

    【总结】

    样例数据是万能的,不能过于相信样例,但是样例错了那就肯定错了

     

     

    (另外,之前看见有人说原本想并查集但是错了,我个人没有想通为何不能简单的用并查集来偷懒,希望大佬能指点我一番)

  • 相关阅读:
    cocos2d-X json
    CSS3背景 background-size
    HTML、CSS、meta常用代码
    less相关知识点总结
    使用elementUI滚动条之横向滚动
    text-fill-color:仿苹果官网介绍效果 CSS设置文字渐变效果 文字背景图遮罩
    CSS 解析原理_你知道浏览器CSS是如何解析吗?
    CSS新特性contain,控制页面的重绘与重排
    php使用 header 头下载文件
    Vue单页面应用阻止浏览器记住密码
  • 原文地址:https://www.cnblogs.com/Danzel-Aria233/p/7774694.html
Copyright © 2011-2022 走看看