zoukankan      html  css  js  c++  java
  • Luogu P3916 图的遍历 【优雅的dfs】【内有待填坑】By cellur925

    说明

    • 对于60% 的数据, n,m在1e3内

    • 对于100% 的数据, n,m在1e5内

    本弱弱上来就是一顿暴搜打,dfs n次,每次更新答案,复杂度为O(n*n),果然TLE,60分抱回家。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring> 
     4 
     5 using namespace std;
     6 
     7 int n,m,tot,head[100090],vis[100090],f[100090];
     8 struct node{
     9     int to,next;
    10 }edge[100090];
    11 
    12 void add(int x,int y)
    13 {
    14     edge[++tot].next=head[x];
    15     head[x]=tot;
    16     edge[tot].to=y;
    17 }
    18 
    19 void dfs(int x)
    20 {
    21     vis[x]=1;
    22     for(int i=head[x];i;i=edge[i].next)
    23     {
    24         int v=edge[i].to;
    25         if(vis[v]) continue;
    26         dfs(v);
    27         f[x]=max(f[x],f[v]);
    28     }
    29 }
    30 
    31 int main()
    32 {
    33     scanf("%d%d",&n,&m);
    34     for(int i=1;i<=m;i++)
    35     {
    36         int x=0,y=0;
    37         scanf("%d%d",&x,&y);
    38         add(x,y);
    39     }
    40     for(int i=1;i<=n;i++) f[i]=i;
    41     for(int i=1;i<=n;i++)
    42     {
    43         dfs(i);
    44         memset(vis,0,sizeof(vis));
    45     }
    46     for(int i=1;i<=n;i++) printf("%d ",f[i]);
    47     return 0;
    48 }

    然后就通往了题解。我们可以转化一下思维:求多个点到一个点,不妨从最大的点出发倒着遍历,反向连边,这样每个点只会被访问一次,复杂度O(n).

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring> 
     4 
     5 using namespace std;
     6 
     7 int n,m,tot,head[100090],f[100090];
     8 struct node{
     9     int to,next;
    10 }edge[100090];
    11 
    12 void add(int x,int y)
    13 {
    14     edge[++tot].next=head[x];
    15     head[x]=tot;
    16     edge[tot].to=y;
    17 }
    18 
    19 void dfs(int noww,int st)
    20 {
    21     if(f[noww]) return ;
    22     f[noww]=st;
    23     for(int i=head[noww];i;i=edge[i].next)
    24      if(!f[edge[i].to]) dfs(edge[i].to,st);
    25 }
    26 
    27 int main()
    28 {
    29     scanf("%d%d",&n,&m);
    30     for(int i=1;i<=m;i++)
    31     {
    32         int x=0,y=0;
    33         scanf("%d%d",&x,&y);
    34         add(y,x);
    35     }
    36     for(int i=n;i>=1;i--)
    37      dfs(i,i);
    38     for(int i=1;i<=n;i++) printf("%d ",f[i]);
    39     return 0;
    40 }

    ps:真的这样结束了嘛?

    脑洞:若求所能到达的节点编号最小???

               在无向图中???

    大坑待填。

  • 相关阅读:
    开发中的问题
    页面重定向Redirect时产生错误
    项目管理的几个阶段及分工
    让你的CSS像Jquery一样做筛选
    项目中的几个SQL程序
    SharePoint2010人员搜索配置心得
    TroubleShoot:该搜索请求无法连接到搜索服务
    转:软件架构师应该知道的97件事
    通用动态生成静态HTML页方法
    简单的正则表达式过滤网址
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9416748.html
Copyright © 2011-2022 走看看