强连通分量——tarjan
来源:互联网 发布:知道mac地址怎么查ip 编辑:程序博客网 时间:2024/06/06 05:26
洛谷 P2812 校园网络
洛谷 P3387 缩点
洛谷P2812 校园网络
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;struct arr{ int nd,nx;}bot[1100000],d[1100000];int head[20000],h[20000],stack[20000],low[20000],dfn[20000],bl[20000];int rd[20000],cd[20000],tot,cnt,pos,top,scc,size[20000],n;bool instack[20000];inline int read(){ int x=0,w=1;char ch=0; while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); if(ch=='-') w=-1,ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch-48),ch=getchar(); return x*w; }inline void add(int a,int b){bot[++cnt].nd=b;bot[cnt].nx=head[a];head[a]=cnt;}inline void ad1(int a,int b){d[++tot].nd=b;d[tot].nx=h[a];h[a]=tot;rd[b]++;cd[a]++;}inline void tarjan(int u){ dfn[u]=low[u]=++pos; stack[++top]=u;instack[u]=true; for(register int i=head[u];i;i=bot[i].nx) { int v=bot[i].nd; if(instack[v]) low[u]=min(dfn[v],low[u]); if(dfn[v]==0) {tarjan(v);low[u]=min(low[v],low[u]);} } if(low[u]==dfn[u]){ ++scc;int t=0; while(u!=t){ t=stack[top--];instack[t]=false;bl[t]=scc;size[scc]++; } }}int main(){ n=read(); for(register int i=1;i<=n;++i) {int x=read();while(x){ add(i,x); x=read(); }} for(register int i=1;i<=n;++i) if(!dfn[i])tarjan(i); tot=0; for(register int i=1;i<=n;++i) for(register int j=head[i];j;j=bot[j].nx){ int v=bot[j].nd; if(bl[i]!=bl[v]) ad1(bl[i],bl[v]); } int ans1=0,ans2=0; for(register int i=1;i<=scc;++i){//统计一下缩点之后的入度和出度 if(!rd[i]) ans1++; if(!cd[i]) ans2++; } if(scc==1) printf("1\n0"); else printf("%d\n%d",ans1,max(ans1,ans2));}
洛谷 P3387 缩点
一道模板题,就直接贴代码了。
下面这份代码是先tarjan缩点,再建立一个新图,然后加上SPFA
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<queue>using namespace std;struct arr{ int nd,nx;}bot[1100000],d[1100000];int head[100000],h[100000],stack[100000],low[100000],dfn[100000],bl[100000];int tot,cnt,pos,top,scc,m,n;int c[100000],w[100000];long long dist[100000],f[100000];long long ans;bool instack[100000];inline int read(){ int x=0,w=1;char ch=0; while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); if(ch=='-') w=-1,ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch-48),ch=getchar(); return x*w;}inline void add(int a,int b){bot[++cnt].nd=b;bot[cnt].nx=head[a];head[a]=cnt;}inline void ad1(int a,int b){d[++tot].nd=b;d[tot].nx=h[a];h[a]=tot;}inline void tarjan(int u){ dfn[u]=low[u]=++pos; stack[++top]=u;instack[u]=true; for(register int i=head[u];i;i=bot[i].nx){ int v=bot[i].nd; if(!dfn[v]) { tarjan(v);low[u]=min(low[v],low[u]);} if(instack[v]) low[u]=min(dfn[v],low[u]); } if(dfn[u]==low[u]){ int t=0;++scc; while(u!=t){ t=stack[top--];instack[t]=false;bl[t]=scc;c[scc]+=w[t];} }}inline void SPFA(int s){ deque<int>q; for(int i=1;i<=n;i++) dist[i]=0,f[i]=0; dist[s]=c[s];f[s]=1; q.push_back(s); while(!q.empty()){ int now=q.front(); q.pop_front(); f[now]=0; for(register int i=h[now];i;i=d[i].nx){ int v=d[i].nd; if(dist[v]<dist[now]+c[v]){ dist[v]=dist[now]+c[v]; if(!f[v]){ f[v]=1; if(q.empty()||dist[v]>dist[q.front()]) q.push_back(v); else q.push_front(v); } } } } for(register int i=1;i<=scc;++i) if(ans<dist[i]) ans=dist[i];}int main(){ n=read(); m=read(); for(register int i=1;i<=n;++i) w[i]=read(); for(register int i=1;i<=m;++i) { int u=read(),v=read(); add(u,v); } for(register int i=1;i<=n;++i) if(!dfn[i]) tarjan(i); for(register int i=1;i<=n;++i) for(register int j=head[i];j;j=bot[j].nx) { int v=bot[j].nd; if(bl[i]!=bl[v]) ad1(bl[i],bl[v]); } for(register int i=1;i<=scc;++i) SPFA(i); //对于缩点后新建的图跑SPFA printf("%d\n",ans);}
下面这个代码是先tarjan缩点,建立一个新图,然后加上拓扑排序求最长路。
(本蒟一开始做的时候只有40分,后面请了机房某xxy大佬帮我改了下才过的)
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<queue>using namespace std;struct arr{ int nd,nx;}bot[210000],d[210000];int head[20000],a[20000],h[20000];int rd[20000],cd[20000],dis[20000],topo[30000];int low[20000],dfn[20000],stack[20000],instack[20000],bl[20000],size[20000],c[20000];int n,m,cnt,tot,tt,top,pos,scc,ans;inline int read(){ int x=0,w=1;char ch=0; while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); if(ch=='-') w=-1,ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch-48),ch=getchar(); return x*w;}inline void add(int a,int b) { bot[++cnt].nd=b; bot[cnt].nx=head[a]; head[a]=cnt; }inline void ad1(int a,int b) { d[++tot].nd=b; d[tot].nx=h[a]; h[a]=tot;rd[b]++;cd[a]++;}inline void tarjan(int u){ dfn[u]=low[u]=++pos; stack[++top]=u; instack[u]=true; for(register int i=head[u];i;i=bot[i].nx) { int v=bot[i].nd; if(!dfn[v]) { tarjan(v);low[u]=min(low[u],low[v]); } if(instack[v]) {low[u]=min(dfn[v],low[u]);} } if(dfn[u]==low[u]) { int t=0;++scc; while(t!=u) { t=stack[top--]; instack[t]=false; bl[t]=scc; size[scc]++; c[scc]+=a[t];} }}inline void tuopu(){ queue<int> q; for(register int i=1;i<=scc;++i) if(!rd[i]) q.push(i); while(!q.empty()) { int u=q.front();q.pop(); topo[++tt]=u; for(register int i=h[u];i;i=d[i].nx) { int v=d[i].nd;--rd[v]; if(!rd[v]) q.push(v); } } for(register int i=1;i<=scc;++i) dis[i]=c[i]; int ans=0; for(int k=1;k<=tt;++k) { int u=topo[k]; for(register int i=h[u];i;i=d[i].nx) { int v=d[i].nd; dis[v]=max(dis[v],dis[u]+c[v]); } } for(register int i=1;i<=scc;++i) ans=max(ans,dis[i]); printf("%d\n",ans);}int main(){ n=read();m=read(); for(register int i=1;i<=n;++i) a[i]=read(); for(register int i=1;i<=m;++i) { int u=read(),v=read(); add(u,v); } for(register int i=1;i<=n;++i)if(!dfn[i]) tarjan(i); for(register int i=1;i<=n;++i) for(register int j=head[i];j;j=bot[j].nx) { int v=bot[j].nd; if(bl[i]!=bl[v]) { ad1(bl[i],bl[v]); }//建立新图的时候要注意加入的点是bl[i]和bl[v],不是i和v,错了好几次 } tuopu(); return 0;}
阅读全文
0 0
- 强连通分量——tarjan
- 强连通分量——tarjan
- 强连通分量tarjan
- 强连通分量 Tarjan
- Tarjan强连通分量
- 强连通分量-Tarjan
- 求强连通分量——Tarjan、Kosaraju算法
- tarjan——有向图强连通分量
- Tarjan算法的学习——求强连通分量
- 强连通分量——tarjan ->缩点
- *有向图强连通分量——Tarjan
- tarjan求强连通分量
- 强连通分量 Tarjan算法
- POJ1236强连通分量tarjan
- 强连通分量 tarjan算法
- poj1236强连通分量(Tarjan)
- tarjan 求强连通分量
- 强连通分量Tarjan模板
- 顺序存储的稀疏矩阵(三元组)的转置
- 从铁路技术装备展的科技“攀比”看合作共赢
- POJ 3080.Blue Jeans
- hdu1010 Tempter of the Bone(dfs) java
- VS2012尝试运行项目时出错 无法启动程序 请参见应用程序日志时间
- 强连通分量——tarjan
- 第二讲 类加载器
- Leetcode 5. Longest Palindromic Substring(java版)
- 4 Values whose Sum is 0(poj 2785)
- shiro的org.apache.shiro.UnavailableSecurityManagerException错误
- a messy week
- Java/JDK配置环境变量
- 关于android无法取消标题栏的解决办法
- 最长上升连续子序列-LintCode