[2016-04-01][codeforces][659E][New Reform]
Posted 红洋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[2016-04-01][codeforces][659E][New Reform]相关的知识,希望对你有一定的参考价值。
时间:2016-04-01 19:27:59 星期五
题目编号:[2016-04-01][codeforces][659E][New Reform]
题目大意:给定n个城市,m条路,每条路连接两个城市,每两个城市最多只有一条路连接,现在把路改成单项的,问最少会出现几个孤立的城市(没有城市到达它),
分析:
- 在一个联通分支中,如果边数为n - 1,那么这个图就是树,树上除了根节点,其他节点都可达,如果边数大于n-1,那么至少会出现一个环,只要选的点在环上,那么所有的点都可达
- 题目不止一个联通分支,
- 第一个方法T了,用并查集处理整个图,从每个联通分支的父节点出发,求边数,更新最终答案–>这个T了
- 用并查集存图,扫一遍所有节点,更新所有节点的度数和到父节点上,则边数等于总度数/2,更新每个联通分支的节点数到父节点上
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 1E5 + 10;
int fa[maxn],d[maxn],cnt[maxn];
inline void ini(int n){
for(int i = 0; i <= n ;++i){
fa[i] = i;
}
memset(d,0,sizeof(int) * (n + 1));
memset(cnt,0,sizeof(int) * (n + 1));
}
int fnd(int x){
return fa[x] == x ? x:fa[x] = fnd(fa[x]);
}
inline void uni(int x,int y){
fa[fnd(x)] = fnd(y);
}
int main(){
int n,m,a,b;
scanf("%d%d",&n,&m);
ini(n);
for(int i = 0;i < m ; ++i){
scanf("%d%d",&a,&b);
++d[a];++d[b];
uni(a,b);
}
int f;
for(int i = 1;i <= n ; ++i){
f = fnd(i);
++cnt[f];
if(f != i) d[f] += d[i];
}
int ans = 0;
for(int i = 1; i <= n ; ++i){
if(fa[i] == i && cnt[i] == d[i] / 2 + 1){
++ans;
}
}
printf("%d\n",ans);
return 0;
}
以上是关于[2016-04-01][codeforces][659E][New Reform]的主要内容,如果未能解决你的问题,请参考以下文章