dfs
问题 C: NH树
时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
小明终于忙玩了各种各样的课程,终于可以继续学习算法了。
他在图论书上看到了树,树有许许多多特殊的性质。小明一下子就喜欢上了这种特殊的树。
于是,他发明了自己的对于无向图的评分方法。
一个无向图的分数定义为,各个连通块是树的数量。
现在给定一个 n 个点 m 条边的无向图,问在小明的评分方法下,分数为多少。
一个连通块是树,当且仅当边数比点数少 1。
输入
第一行两个整数 n 和 m,表示图的点数和边数。
第二行有 m 对整数,u 和 v 表示,结点 u 和节点 v 之间有边。
给出的无向图不存在重边。
输出
输出一行包括一个整数,表示无向图的评分,也就是树的数量。
样例输入 Copy
8 6
1 2
1 3
2 4
5 6
6 7
5 7
样例输出 Copy
2
提示
20%的数据,1<=n<=2000
100%的数据,1<=n<=100000,0<=m<=min(n*(n-1)/2,200000)
#include<bits/stdc++.h>
using namespace std;
vector<int>A[100005];//二维存不下
int v[100005],f;//对准一维上
void dfs(int i,int last)
{
v[i]=1;
for(int j=0;j<A[i].size();j++)
{
if(v[A[i][j]]==1)//
{
if(A[i][j]!=last)//不等于上一个意思就是等于前面已经访问过的,那必然是环(这个是无向的)
{
f=0;
}
}
else
{
dfs(A[i][j],i);
}
}
}
int main()
{
int n,m;
scanf("%d %d",&n,&m);//注意是无向图
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d %d",&a,&b);
A[a].push_back(b);
A[b].push_back(a);//存图
}
//这种存法类似于南门的数,自动排好了一维上的序
int cnt=0;
for(int i=1;i<=n;i++)
{
if(v[i]==0)
{
f=1;
dfs(i,-1);
if(f==1)
{
cnt++;
}
}
}
printf("%d",cnt);
return 0;
}
升级版 南门的数
#include<bits/stdc++.h>
using namespace std;
int A[1000005],order[1000005];
bool cmp(int x,int y)
{
return x<y;
}
int main()
{
int n,maxn=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&A[i]);
}
sort(A+1,A+1+n,cmp);
int i;
for(i=2;i<=n;i++)
{
if(A[i]==A[i-1])
{
order[i]=order[i-1]+1;
}
maxn=max(maxn,order[i]);
}
int cnt=0;
for(int i=1;i<=n;i++)
{
if(order[i]==maxn) cnt++;
}
printf("%d\n",cnt);
for(int i=1;i<=n;i++)
if(order[i]==maxn) printf("%d ",A[i]);
return 0;
}