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 }

 

posted @ 2018-10-15 19:10  MJT12044  阅读(250)  评论(0编辑  收藏  举报