2438: [中山市选2011]杀人游戏
2438: [中山市选2011]杀人游戏
https://www.lydsy.com/JudgeOnline/problem.php?id=2438
分析:
a认识b,b认识c,a认识c。开始时以为只会告诉一层。
建出图来后,如果是树的话,那么直接查根节点就行了。那么无向图就缩点一下。
有一种情况就是知道了n-1个人的情况,可以推出第n个人的情况。那么这个人需要满足:是根节点(没有入度),强联通分量内只有他一个点,他所连向的点可以有其他人知道。
代码:
1 /* 2 * @Author: mjt 3 * @Date: 2018-10-15 17:11:06 4 * @Last Modified by: mjt 5 * @Last Modified time: 2018-10-15 18:47:34 6 */ 7 #include<cstdio> 8 #include<algorithm> 9 #include<cstring> 10 #include<cmath> 11 #include<iostream> 12 #include<cctype> 13 #include<set> 14 #include<vector> 15 #include<queue> 16 #include<map> 17 #define fi(s) freopen(s,"r",stdin); 18 #define fo(s) freopen(s,"w",stdout); 19 using namespace std; 20 typedef long long LL; 21 22 inline int read() { 23 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 24 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 25 } 26 27 const int N = 100005; 28 29 int head[N], nxt[N * 6], to[N * 6], En; 30 int dfn[N], low[N], sk[N], deg[N], bel[N], siz[N], Time_Index, top, Scc, n, m; 31 bool vis[N]; 32 vector<int> T[N]; 33 34 void add_edge(int u,int v) { 35 ++En; to[En] = v; nxt[En] = head[u]; head[u] = En; 36 } 37 void add_edge2(int u,int v) { 38 T[u].push_back(v); deg[v] ++; vis[v] = true; 39 } 40 41 void tarjan(int u) { 42 dfn[u] = low[u] = ++Time_Index; 43 sk[++top] = u; vis[u] = 1; 44 for (int i=head[u]; i; i=nxt[i]) { 45 int v = to[i]; 46 if (!dfn[v]) { 47 tarjan(v); 48 low[u] = min(low[u], low[v]); 49 } 50 else if (vis[v]) low[u] = min(low[u], dfn[v]); 51 } 52 if (low[u] == dfn[u]) { 53 ++Scc; 54 do { 55 vis[sk[top]] = false; 56 bel[sk[top]] = Scc; 57 siz[Scc] ++; 58 top --; 59 } while (sk[top + 1] != u) ; 60 } 61 } 62 63 void rebuild() { 64 memset(vis, false, sizeof(vis)); 65 for (int u=1; u<=n; ++u) { 66 for (int i=head[u]; i; i=nxt[i]) { 67 int v = to[i]; 68 if (!vis[bel[v]] && bel[u] != bel[v]) add_edge2(bel[u], bel[v]); 69 } 70 for (int i=head[u]; i; i=nxt[i]) { 71 int v = to[i]; 72 if (bel[u] != bel[v]) vis[bel[v]] = false; 73 } 74 } 75 } 76 77 bool check(int x) { 78 if (deg[x] || siz[x] > 1) return 0; 79 for (int sz=T[x].size(),i=0; i<sz; ++i) if (deg[T[x][i]] == 1) return 0; 80 return 1; 81 } 82 83 int main() { 84 n = read(), m = read(); 85 for (int i=1; i<=m; ++i) { // n - 1 !!! 86 int u = read(), v = read(); 87 add_edge(u, v); 88 } 89 for (int i=1; i<=n; ++i) 90 if (!dfn[i]) tarjan(i); 91 rebuild(); 92 int ans = 0; 93 for (int i=1; i<=Scc; ++i) ans += (!deg[i] ? 1 : 0); 94 for (int i=1; i<=Scc; ++i) { 95 if (check(i)) {ans --; break; }; 96 } 97 printf("%.6lf", (double)(n - ans) / (double)(n)); 98 return 0; 99 }