zoukankan      html  css  js  c++  java
  • [模板]tarjan缩点+拓扑排序

    题目:给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。

       允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。

    题目简述:先tarjan缩点,再从入度为零处进行一次拓扑排序,求最长路即可,话说拓扑排序求最长路真方便。。。

    注意: 要明确拓扑的写法,用栈写最优。

        再进行拓扑排序之前我们要进行将点权转化为边权的操作,具体操作看拓扑排序。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define man 100010
     4 inline int sc()
     5 {    int x=0,f=1;char ch=getchar();
     6     while(!isdigit(ch)){    if(ch==45)f=-1;ch=getchar();}
     7     while(isdigit(ch)) {    x=x*10+ch-48;ch=getchar();}
     8     return x*f;
     9     }
    10 /*TEST*/
    11 int n,m,c[man],x[man],y[man];
    12 /*EDGE*/
    13 int head[man<<1],num=0;
    14 struct edge
    15 {    int next,to,dis;}e[man<<2];
    16 inline void add(int from,int to,int dis) 
    17 {    e[++num].next=head[from];
    18     e[num].to=to;
    19     e[num].dis=dis;
    20     head[from]=num;
    21     }
    22 /*TARJAN*/
    23 int dfn[man],low[man],bel[man],val[man],cnt=0,dep=0;
    24 bool vis[man];
    25 int sta[man],top=0;
    26 void tarjan(int s)
    27 {    low[s]=dfn[s]=++dep;vis[s]=1;sta[++top]=s;
    28     for(int i=head[s];i;i=e[i].next)
    29     {    int to=e[i].to;
    30         if(!dfn[to])
    31         {    tarjan(to);
    32             low[s]=min(low[s],low[to]);
    33             }
    34         else if(vis[to])
    35         {    low[s]=min(low[s],dfn[to]);}
    36         }
    37     if(low[s]==dfn[s])
    38     {    int j;cnt++;
    39         do
    40         {    j=sta[top--];
    41             vis[j]=0;
    42             val[cnt]+=c[j];
    43             bel[j]=cnt;
    44             }while(j!=s);
    45         }
    46     }
    47 /*TOPSORT*/
    48 inline void clear()
    49 {    memset(e,0,sizeof(e));
    50     memset(head,0,sizeof(head));
    51     num=0;
    52     }
    53 int degree[man],dis[man];
    54 inline void topsort()
    55 {    queue<int >q;
    56     for(int i=1;i<=cnt;i++)
    57         dis[i]=0;
    58     for(int i=1;i<=cnt;i++)
    59         if(degree[i]==0) q.push(i),dis[i]=val[i];
    60     while(q.size()!=0)
    61     {    int u=q.front();q.pop();
    62         for(int i=head[u];i;i=e[i].next)
    63         {    int to=e[i].to;
    64             degree[to]--;
    65             if(degree[to]==0) q.push(to);
    66             dis[to]=max(dis[to],dis[u]+e[i].dis);
    67             }
    68         }
    69     int ans=0;
    70     for(int i=1;i<=cnt;i++)
    71         ans=max(ans,dis[i]);
    72     printf("%d
    ",ans);
    73     }
    74 int main()
    75 {    n=sc();m=sc();
    76     for(int i=1;i<=n;i++)
    77         c[i]=sc();
    78     for(int i=1;i<=m;i++)
    79     {    x[i]=sc(),y[i]=sc();
    80         add(x[i],y[i],0);
    81         }
    82     for(int i=1;i<=n;i++)
    83         if(!dfn[i]) tarjan(i);
    84     clear();
    85     for(int i=1;i<=m;i++)
    86     {    if(bel[ x[i] ]==bel[ y[i] ]) continue;
    87         add(bel[x[i]],bel[y[i]],val[bel[y[i]]]);
    88         degree[bel[y[i]]]++;
    89         }
    90     topsort();
    91     return 0;
    92     } 
  • 相关阅读:
    pyspark使用及原理
    谷歌地图聚合点使用(GoogleMaps MarkerCluster)
    struts2升级到2.5的配置
    二进制反码补码
    进制转换
    JAVA基础第一章
    TypeError: unhashable type: 'list' 如何解决?
    剪辑模板
    Mysql三天入门(三) 数据库设计的三范式
    Mysql三天入门(三) DBA命令
  • 原文地址:https://www.cnblogs.com/Slager-Z/p/7784857.html
Copyright © 2011-2022 走看看