Codeforces 659E 找环+(并查集/dfs)

来源:互联网 发布:会计应对大数据时代 编辑:程序博客网 时间:2024/05/17 06:58

题目:
http://codeforces.com/problemset/problem/659/E
题意:
给你一个图,现在要你给这个图里面的边定方向,使得入度为0的点最少。
分析:
对于一个连通块而言,如果里面存在一个环,那么必然所有点的入度都可以大于等于1
否则的话,就存在一个点的入度为0。

并查集:

#include <bits/stdc++.h>using namespace std;int n, m, u, v, fa[100005], a[100005];int findfa(int x){return fa[x] == x? x : fa[x] = findfa(fa[x]);}int main(){    scanf("%d%d", &n, &m);    for (int i = 1; i <= n; i++) fa[i] = i, a[i] =0;    for (int i = 1; i <= m; i++)    {        scanf("%d%d", &u, &v);        u = findfa(u), v = findfa(v);        if (u == v) a[u]++; //有环,标记一下        else            fa[u] = v,a[v]+=a[u];    }    int ans = 0;    for (int i = 1; i <= n; i++)    {        if (findfa(i) == i) ans += a[i]==0? 1 : 0;    }    printf("%d\n", ans);    return 0;}

看到网上的题解大多数是dfs,这也更好理解:

#include<bits/stdc++.h>using namespace std;const int N=1e5+5;vector<int>a[N];int flag;bool vis[N];void dfs(int u,int pre){    if(vis[u]){        flag=0;        return;    }    vis[u]=1;    for(int i=0;i<a[u].size();i++){        if(a[u][i]!=pre){            dfs(a[u][i],u);        }    }}int main(){    int n,m;    scanf("%d%d",&n,&m);    int x,y;    for(int i=0;i<m;i++){        scanf("%d%d",&x,&y);        a[x].push_back(y);        a[y].push_back(x);    }    int ans=0;    for(int i=1;i<=n;i++){        if(!vis[i]){            flag=1;            dfs(i,-1);            ans+=flag;        }    }    printf("%d\n",ans);    return 0;}
0 0