Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 13349 | Accepted: 5338 |
Description
Input
Output
Sample Input
5 2 4 3 0 4 5 0 0 0 1 0
Sample Output
12
题意:给你一个N个点的有向图,问1,最少连接几个点可以直接或间接 连接到所有点。2,最少增加几条边使图强连通。
较简单的SCC题目,这里只说下思路吧。
思路:SCC + 缩点后。统计出入度为0的SCC数sumin和出度为0的SCC数sumout。
答案一就是sumin,答案二就是max(sumin, sumout)。注意只有一个SCC时,输出1 0。
有人请吃饭,O(∩_∩)O~ 回来再刷题。
AC代码:
#include <cstdio> #include <cstring> #include <stack> #include <queue> #include <vector> #include <algorithm> #define MAXN 100+10 #define MAXM 10000+10 #define INF 0x3f3f3f3f using namespace std; struct Edge { int from, to, next; }; Edge edge[MAXM]; int head[MAXN], edgenum; int low[MAXN], dfn[MAXN]; int dfs_clock; int sccno[MAXN], scc_cnt; stack<int> S; bool Instack[MAXN]; int N; void init() { edgenum = 0; memset(head, -1, sizeof(head)); } void addEdge(int u, int v) { Edge E = {u, v, head[u]}; edge[edgenum] = E; head[u] = edgenum++; } void getMap() { int y; for(int i = 1; i <= N; i++) { while(scanf("%d", &y), y) addEdge(i, y); } } void tarjan(int u, int fa) { int v; low[u] = dfn[u] = ++dfs_clock; S.push(u); Instack[u] = true; for(int i = head[u]; i != -1; i = edge[i].next) { v = edge[i].to; if(!dfn[v]) { tarjan(v, u); low[u] = min(low[u], low[v]); } else if(Instack[v]) low[u] = min(low[u], dfn[v]); } if(low[u] == dfn[u]) { scc_cnt++; for(;;) { v = S.top(); S.pop(); Instack[v] = false; sccno[v] = scc_cnt; if(v == u) break; } } } void find_cut(int l, int r) { memset(low, 0, sizeof(low)); memset(dfn, 0, sizeof(dfn)); memset(sccno, 0, sizeof(sccno)); memset(Instack, false, sizeof(Instack)); dfs_clock = scc_cnt = 0; for(int i = l; i <= r; i++) if(!dfn[i]) tarjan(i, -1); } int in[MAXN], out[MAXN];//记录SCC出度和入度 void suodian() { for(int i = 1; i <= scc_cnt; i++) in[i] = out[i] = 0; for(int i = 0; i < edgenum; i++) { int u = sccno[edge[i].from]; int v = sccno[edge[i].to]; if(u != v) in[v]++, out[u]++; } } void solve() { find_cut(1, N); suodian(); if(scc_cnt == 1)//一个SCC { printf("1\n0\n"); return ; } int sumin = 0, sumout = 0;//记录入度为0的SCC和出度为0的SCC for(int i = 1; i <= scc_cnt; i++) { if(in[i] == 0) sumin++; if(out[i] == 0) sumout++; } printf("%d\n%d\n", sumin, max(sumin, sumout)); } int main() { while(scanf("%d", &N) != EOF) { init(); getMap(); solve(); } return 0; }