zoukankan      html  css  js  c++  java
  • Gym

    题意:求一个有向图上的最长路(每个强连通分量的点不超过5个)

    首先对强连通分量缩点,暴力预处理出len[k][i][j]表示第k个强连通分量里的第i个点和第j个点之间的最长路径,设状态(k,i,f)表示在第k个强连通分量的第i个点,f表示是否已经在内部发生了转移(每个强连通分量内部只允许转移一次),然后记忆化搜索即可。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=1e5+10;
     4 int n,m,hd[N],ne,low[N],dfn[N],nscc,scc[N],siz[N],sta[N],tp,tot;
     5 int id[N],ID[N][5],G[N][5][5],len[N][5][5],vis[5],dp[N][5][2];
     6 struct E {int v,nxt;} e[(int)1e6+10];
     7 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
     8 void Tarjan(int u) {
     9     low[u]=dfn[u]=++tot,sta[++tp]=u;
    10     for(int i=hd[u]; ~i; i=e[i].nxt) {
    11         int v=e[i].v;
    12         if(!dfn[v])Tarjan(v),low[u]=min(low[u],low[v]);
    13         else if(!scc[v])low[u]=min(low[u],dfn[v]);
    14     }
    15     if(low[u]==dfn[u])for(++nscc; !scc[u];) {
    16             int v=sta[tp--];
    17             scc[v]=nscc,id[v]=siz[nscc]++,ID[scc[v]][id[v]]=v;
    18         }
    19 }
    20 void dfs(int u,int l,int sc,int fr) {
    21     if(vis[u])return;
    22     vis[u]=1;
    23     len[sc][fr][u]=max(len[sc][fr][u],l);
    24     for(int i=0; i<siz[sc]; ++i)if(G[sc][u][i])dfs(i,l+1,sc,fr);
    25     vis[u]=0;
    26 }
    27 int dfs2(int sc,int u,int f) {
    28     int& ret=dp[sc][u][f];
    29     if(~ret)return ret;
    30     ret=0;
    31     int U=ID[sc][u];
    32     for(int i=hd[U]; ~i; i=e[i].nxt) {
    33         int V=e[i].v,v=id[V];
    34         if(scc[U]!=scc[V])ret=max(ret,dfs2(scc[V],v,0)+1);
    35     }
    36     if(!f)for(int v=0; v<siz[sc]; ++v)if(len[sc][u][v])
    37                 ret=max(ret,dfs2(sc,v,1)+len[sc][u][v]);
    38     return ret;
    39 }
    40 void getscc() {
    41     memset(siz,0,sizeof siz);
    42     memset(dfn,0,sizeof dfn);
    43     tot=nscc=0,tp=-1;
    44     for(int i=1; i<=n; ++i)if(!dfn[i])Tarjan(i);
    45 }
    46 int main() {
    47     memset(hd,-1,sizeof hd),ne=0;
    48     scanf("%d%d",&n,&m);
    49     while(m--) {
    50         int u,v;
    51         scanf("%d%d",&u,&v);
    52         addedge(u,v);
    53     }
    54     getscc();
    55     memset(G,0,sizeof G);
    56     for(int u=1; u<=n; ++u) {
    57         for(int i=hd[u]; ~i; i=e[i].nxt) {
    58             int v=e[i].v;
    59             if(scc[u]==scc[v])G[scc[u]][id[u]][id[v]]=1;
    60         }
    61     }
    62     for(int i=1; i<=nscc; ++i)
    63         for(int j=0; j<siz[i]; ++j)dfs(j,0,i,j);
    64     memset(dp,-1,sizeof dp);
    65     int ans=0;
    66     for(int i=1; i<=n; ++i)ans=max(ans,dfs2(scc[i],id[i],0));
    67     printf("%d
    ",ans+1);
    68     return 0;
    69 }
  • 相关阅读:
    HQL语句中类的别名语法以及作用?
    C#面向对象
    c#异步编程一
    c#接口
    c#Socket通信基本使用
    c#FTP基本使用
    c#XML的基本使用
    c#装箱与拆箱
    c#数组与集合
    c#中for与foreach的使用
  • 原文地址:https://www.cnblogs.com/asdfsag/p/11285683.html
Copyright © 2011-2022 走看看