1 条题解
-
0
题意 给出一个有向图,求图的一个子集。
这个子集中的所有点都是汇点(u是图中的一个顶点,对于图中的每一个顶点v,如果u可以到达v,那么v也可以到达u)。
思路 一个强联通分量可以保证任意点互相可以到达。但是不一定满足题意中的条件。
因为强连通分量中的点如果指向了另一个分量中的点,就不满足题目的条件了。
所以我们要求的就是缩点之后,出度为0的强联通分量的所有点。
代码 ————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_43236122/article/details/105405472
//#include<bits/stdc++.h> #include<algorithm> #include<string.h> #include<stdio.h> #include<iostream> #include<queue> #include<map> #include<time.h> #define pb push_back #define read(a) scanf("%d",&a) #define out(a) printf("%d\n",a) using namespace std; typedef long long ll; typedef unsigned long long ull; const int N=1e6+10; const int mod=1000000007; const ll inf=0x3f3f3f3f3f3f3f3f; vector<int>vec[N],ans; int dfn[N],low[N],Stack[N],vis[N],bel[N],out[N]; int top,tot,num; void tarjan(int u) { dfn[u]=low[u]=++tot; Stack[top++]=u; vis[u]=1; for(int i=0;i<vec[u].size();i++) { int v=vec[u][i]; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(vis[v]&&dfn[v]<low[u]) low[u]=dfn[v]; } if(dfn[u]==low[u]) { int v; num++; do { v=Stack[--top]; bel[v]=num; vis[v]=0; } while(u!=v); } } int main() { int n,m; while(~scanf("%d",&n)&&n) { memset(dfn,0,sizeof(dfn)); memset(out,0,sizeof(out)); memset(vis,0,sizeof(vis)); num=top=tot=0; read(m); for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); vec[u].pb(v); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++) { for(int j=0;j<vec[i].size();j++) { int u=i,v=vec[i][j]; if(bel[u]==bel[v]) continue; out[bel[u]]++; } } for(int i=1;i<=n;i++) vec[i].clear(); for(int i=1;i<=n;i++) if(out[bel[i]]==0) printf("%d ",i); printf("\n"); } return 0; }
- 1
信息
- ID
- 1454
- 时间
- 1000ms
- 内存
- 64MiB
- 难度
- (无)
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者