Gym - 101170B British Menu (强连通缩点+dp)

题意:求一个有向图上的最长路(每个强连通分量的点不超过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\n",ans+1);
68     return 0;
69 }

 

posted @ 2019-08-01 22:05  jrltx  阅读(332)  评论(0编辑  收藏  举报