2018年全国多校算法寒假训练营练习比赛(第四场)-E-通知小弟【强联通】
2018-02-16 20:06
375 查看
题意:
第一行:n个点 m组数据
第二行:HA能通知到的人
第三行——最后一行(1———n):【第一个字表示有几个能通知到的】
思路:
强联通分量个数
缩点后处理
输入
3 2
1 2
1 2
1 1
0
输出
-1
输入
3 1
1
2 2 3
0
0
输出
1
第一行:n个点 m组数据
第二行:HA能通知到的人
第三行——最后一行(1———n):【第一个字表示有几个能通知到的】
思路:
强联通分量个数
缩点后处理
输入
3 2
1 2
1 2
1 1
0
输出
-1
输入
3 1
1
2 2 3
0
0
输出
1
#include<stdio.h> #include<string.h> #include<stack> #include<vector> #include<iostream> using namespace std; #define MAXN 505 int n,m; ///dfn记录节点的被访问时间(时间戳) ///low记录该点或者以这个点为根的子树能够追溯到最早的栈中节点的次序 int dfn[MAXN],low[MAXN]; ///vis标记是否在栈中,num为每个强连通分量的节点数,belong标记节点属于第几个强连通分量 int vis[MAXN],num[MAXN],belong[MAXN]; int cnt,idx; ///cnt为强连通分量的个数,idx为节点访问的编号(每个节点不同) stack<int> s; vector<int> map[MAXN]; void tarjan(int u) { int i,v; dfn[u]=low[u]=++idx; ///新点初始化 s.push(u); ///入栈 vis[u]=1; ///标记在栈中 for(i=0; i<map[u].size(); i++) { ///处理与u相邻的节点 v=map[u][i]; if(!dfn[v]) { ///如果没被访问过,不能用!vis[v],vis表示是否在栈中 tarjan(v); ///递归处理 low[u]=min(low[v],low[u]); ///将强连通分量的所有节点low值改为根节点的dfn值 } ///如果访问过,并且在栈中,表明存在环 else if(vis[v]&&dfn[v]<low[u]) low[u]=dfn[v]; } if(dfn[u]==low[u]) { ///如果是强连通分量子树的最小根,此时栈内u之上的元素构成起一个强连通分量 cnt++; ///第cnt个强连通分量 do { ///输出 也可以开个vector数组存储一下 v=s.top(); s.pop(); vis[v]=0; ///标记不在栈中 belong[v]=cnt; ///节点v属于第cnt个强连通分量 num[cnt]++; } while(u!=v); } } void solve() { int i; cnt=0; idx=0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(vis,0,sizeof(vis)); memset(num,0,sizeof(num)); for(i=1; i<=n; i++) ///如果没被访问过则从该点开始处理,防止有点遗漏 if(!dfn[i]) tarjan(i); } vector<int> mp[MAXN]; ///由所有强连通分量形成的新图 int ru[MAXN]; //入度 void suodian(int n) { ///缩点函数,其中n为节点个数 int i,j,u,v; memset(ru,0,sizeof(ru)); for(i=1; i<=n; i++) mp[i].clear(); for(i=1; i<=n; i++) { ///扫描每个节点 u=belong[i]; ///原来起点所在的强连通分量 for(j=0; j<map[i].size(); j++) { ///每个节点的相邻节点 v=belong[map[i][j]]; ///原来终点所在的强连通分量 if(u!=v) { ///如果不在同一强连通分量内 mp[u].push_back(v); ///形成新图 ru[v]++; } } } } int main() { int i,j,x,f,sum,ans,a[505],mark[505]; while(~scanf("%d%d",&n,&m)) { for(i=0; i<=n; i++) map[i].clear(); for(i=0; i<m; i++) scanf("%d",&a[i]); for(i=1; i<=n; i++) { scanf("%d",&sum); for(j=0; j<sum; j++) { scanf("%d",&x); map[i].push_back(x); } } solve(); suodian(n); memset(mark,0,sizeof(mark)); ///将能通知到的人所在的强联通分量标记 for(i=0; i<m; i++) mark[belong[a[i]]]=1; f=1; ans=0; ///printf("cnt=%d\n",cnt); for(i=1; i<=cnt; i++) { /// if(!mark[i]&&!ru[i]) { ///如果有人没通知到且没人通知的到 f=0; break; } ///如果此人没人通知的到并且间谍老大可以通知到 else if(!ru[i]&&mark[i]) ans++; } if(!f) printf("-1\n"); else printf("%d\n",ans); } return 0; }
相关文章推荐
- 2018年全国多校算法寒假训练营练习比赛(第四场)E 题 通知小弟 强联通
- 2018年全国多校算法寒假训练营练习比赛(第四场)-E:通知小弟(SCC缩点)
- 2018年全国多校算法寒假训练营练习比赛(第四场) E.通知小弟(Tarjan,缩点)
- 2018年全国多校算法寒假训练营练习比赛(第四场) - E - 通知小弟(BFS)
- (*)2018年全国多校算法寒假训练营练习比赛(第四场)E-通知小弟(Kosaraju)
- 2018年全国多校算法寒假训练营练习比赛(第四场)-E-通知小弟(强连通缩点)
- 2018年全国多校算法寒假训练营练习比赛第四场 F Call to your teacher 【DFS+BFS】
- 【2018年全国多校算法寒假训练营练习比赛(第四场)】
- 2018年全国多校算法寒假训练营练习比赛(第四场)C-求交集
- 2018年全国多校算法寒假训练营练习比赛(第四场)E
- 2018年全国多校算法寒假训练营练习比赛(第四场)F-Call to your teacher(dfs)
- 2018年全国多校算法寒假训练营练习比赛(第四场)G-老子的意大利炮呢
- 2018年全国多校算法寒假训练营练习比赛(第四场)H 老子的全排列呢
- 2018年全国多校算法寒假训练营练习比赛(第四场) A 石油采集
- 牛客网 2018年全国多校算法寒假训练营练习比赛(第四场) 题解
- 2018年全国多校算法寒假训练营练习比赛(第四场)F-Call to your teacher
- 2018年全国多校算法寒假训练营练习比赛(第四场) D小明的挖矿之旅 题解
- 2018年全国多校算法寒假训练营练习比赛(第四场)(图论)
- Wannafly 2018年全国多校算法寒假训练营练习比赛(第四场) G 老子的意大利炮昵
- 2018年全国多校算法寒假训练营练习比赛(第四场)F