mayoko’s diary

プロコンとかいろいろ。

Codeforces Round #346 (Div. 2) E. New Reform

解法

連結成分に一つでも閉路があると, すべての頂点の入次数を 1 以上にすることが出来ます。そうでない場合は木になりますが, 一つの頂点を root として, それ以外のすべての頂点の入次数を 1 以上に出来ます。

よって, 各連結成分について閉路があるかを判定できれば良いですが, これは辺の数(edge)と頂点の数(vertex)の比較で判定できます。edge < vertex なら木, そうでないなら閉路があります。

bool done[100100];

void dfs(int now, const vector<vi>& G, vi& vs) {
    done[now] = true;
    vs.push_back(now);
    for (int next : G[now]) if (!done[next]) dfs(next, G, vs);
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n, m;
    cin >> n >> m;
    vector<vi> G(n);
    for (int i = 0; i < m; i++) {
        int a, b;
        cin >> a >> b;
        a--; b--;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    int ans = 0;
    for (int i = 0; i < n; i++) if (!done[i]) {
        vector<int> vs;
        dfs(i, G, vs);
        int edge = 0, vertex = vs.size();
        for (int v : vs) edge += G[v].size();
        edge /= 2;
        if (edge < vertex) ans++;
    }
    cout << ans << endl;
    return 0;
}