• [模板]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     } 
  • 相关阅读:
    MVC5管道处理模型
    http协议下:为什么请求与响应会做到准确误的对应。不会出现请求与响应的错乱
    修改 IIS 队列长度
    修改 ASP.NET 请求队列的限制
    Windows性能查看器:系统的性能信息(I/O,IIS最大连接数,Sql) ,以及解决 asp.net IIS 一二百多用户并发
    详解 ASP.NET异步
    [C#]获得线程池中活动的线程数
    一个http请求就是一个线程吗,java的服务是每收到一个请求就新开一个线程来处理吗
    IIS连接数、IIS并发连接数、IIS最大并发工作线程数、应用程序池的队列长度、应用程序池的...
    ASP.NET MVC 线程和并发
  • 原文地址:https://www.cnblogs.com/Slager-Z/p/7784857.html
Copyright © 2020-2023  润新知