zoukankan      html  css  js  c++  java
  • NOIp 2015信息传递【tarjan/拓扑/并查集】

    一道好的NOIp题目,在赛场上总能用许多算法A掉。比如这道和关押罪犯。

    题目传送门

    法一:tarjan在有向图中跑最小环

    有人从别人口中得知自己信息,等效于出现了一个环。于是 这就变成了一个有向图tarjan强连通分量的板子题。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<stack>
     4 #define maxn 200090
     5 
     6 using namespace std;
     7 
     8 int n,y,tot,ans=999999,dfs_clock,scc_cnt,tong[maxn],dfn[maxn],low[maxn],head[maxn],scc[maxn]; 
     9 stack<int>s;
    10 struct node{
    11     int to,next;
    12 }edge[maxn];
    13 
    14 void add(int x,int y)
    15 {
    16     edge[++tot].to=y;
    17     edge[tot].next=head[x];
    18     head[x]=tot;
    19 }
    20 
    21 void dfs(int p)
    22 {
    23     dfn[p]=low[p]=++dfs_clock;
    24     s.push(p);
    25     for(int i=head[p];i;i=edge[i].next)
    26     {
    27         int y=edge[i].to;
    28         if(!dfn[y])
    29         {
    30             dfs(y);
    31             low[p]=min(low[p],low[y]);
    32         }
    33         else if(!scc[y]) low[p]=min(low[p],dfn[y]);
    34     }
    35     if(dfn[p]==low[p])
    36     {
    37         scc_cnt++;
    38         while(1)
    39         {
    40             int x=s.top();
    41             s.pop();
    42             scc[x]=scc_cnt;
    43             if(x==p) break;
    44         }
    45     }
    46 }
    47 
    48 int main()
    49 {
    50     scanf("%d",&n);
    51     for(int i=1;i<=n;i++)
    52      scanf("%d",&y),add(i,y);
    53     for(int i=1;i<=n;i++)
    54     {
    55         if(!dfn[i]) dfs(i);
    56         tong[scc[i]]++;
    57     }
    58     for(int i=1;i<=scc_cnt;i++) if(tong[i]>1&&tong[i]<ans) ans=tong[i];
    59     printf("%d
    ",ans);
    60     return 0;
    61 }
    View Code

    法二:拓扑排序

    图中可能会出现很多环,求最小的一个。我们跑一遍拓扑排序后,那些不曾入到队列中的点就是成环的点。于是我们可以边拓扑排序边标记最后找到那些在环上的点,从他们出发分别求出环的大小进行比较。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<queue>
     4 
     5 using namespace std;
     6 
     7 int n,x,ans=999999,cnt,tot;
     8 int du[200090],head[200090],vis[200090],flag[200090];
     9 struct node{
    10     int to,next;
    11 }edge[200090];
    12 queue<int>q;
    13 
    14 void add(int x,int y)
    15 {
    16     edge[++tot].next=head[x];
    17     edge[tot].to=y;
    18     head[x]=tot;
    19 }
    20 
    21 void topo()
    22 {
    23     for(int i=1;i<=n;i++)
    24         if(!du[i]) q.push(i),flag[i]=1;
    25     while(!q.empty())
    26     {
    27         int u=q.front();q.pop();
    28         for(int i=head[u];i;i=edge[i].next)
    29         {
    30             int v=edge[i].to;
    31             if(--du[v]==0) q.push(v),flag[v]=1;
    32         }
    33     }
    34 }
    35 
    36 void dfs(int x)
    37 {
    38     vis[x]=1,cnt++;
    39     for(int i=head[x];i;i=edge[i].next)
    40     {
    41         int y=edge[i].to;
    42         if(vis[y]) return ;
    43         dfs(y);
    44     }
    45 }
    46 
    47 int main()
    48 {
    49     scanf("%d",&n);
    50     for(int i=1;i<=n;i++)
    51         scanf("%d",&x),add(i,x),du[x]++;
    52     topo();
    53     for(int i=1;i<=n;i++)
    54         if((!flag[i])&&(!vis[i]))
    55         {
    56             cnt=0;
    57             dfs(i);
    58             ans=min(ans,cnt);
    59         }
    60     printf("%d",ans);
    61     return 0;
    62 }
    View Code

    法三:并查集

    https://anyway.blog.luogu.org/solution-p2661

  • 相关阅读:
    ES基础知识
    ES工具使用
    ES环境部署
    C# 新特性
    自动化测试工程师--面试
    python 报错 pip安装三方库不成功:WARNING: You are using pip version 20.2.3; however, version 20.2.4 is available
    jmeter 测试调用https接口
    JDK升级操作
    Jmeter之post上传文件
    弱网测试—Network-Emulator-Toolkit(一)
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9559041.html
Copyright © 2011-2022 走看看