统计图的连通分支数
思路 建图,搜索,注意这种建图方式是有向图,
反例: 1 2,3 4,4 1这种不会识别出来,因此建图时需要使用有向图,在add阶段加入两个方向的路径;
add时从1开始的边的标号,0用来判断结束,斗则冲突有问题
int tot=0;
const int maxn=1e6;
int nxt[maxn]={0},head[maxn]={0},u[maxn]={0},v[maxn]={0};
int vis[maxn]={0};
void add(int i,int j){
tot++;
nxt[tot]=head[i];
head[i]=tot;
u[tot]=i;
v[tot]=j;
}
int main(){
int x,y;
while (cin>>x>>y)
{
add(x,y);//双向
add(y,x);
}
// 1 2 /3 4/ 4 1如果不是双向这种就不行
int ans=0;
for(int i=1;i<=tot;i++){
// cout<<"i:"<<i<<"\n";
if(vis[i]) continue;
ans++;
// vis[i]=1;
queue<int>q;
q.push(u[i]);
while (q.size())
{
int nowp=q.front();
q.pop();
for(int num=head[nowp];num;num=nxt[num]){
if(vis[num]){
continue;
}
vis[num]=1;
q.push(v[num]);
}
}
}
cout<<ans<<"\n";
return 0;
}
问题 B: 连通图
给定一个无向图和其中的所有边,判断这个图是否所有顶点都是连通的。
**思路:**和上题思路一样;注意细节:每次都全部初始化化为0;
vis数组表示的是某个边是否访问过
const int maxn=1e5;
int head[maxn]={0},u[maxn]={0},v[maxn]={0},vis[maxn],nxt[maxn];
int tot=0;//vis点为是否进入过队列
int nodes[maxn];//访问过的节点
void add(int x,int y){
tot++;
nxt[tot]=head[x];
head[x]=tot;
u[tot]=x;
v[tot]=y;
}
int main(){
int n,m;
while (cin>>n>>m)
{
tot=0;
memset(vis,0,maxn);
memset(head,0,maxn);
memset(nodes,0,maxn);
memset(nxt,0,maxn);
memset(v,0,maxn);
memset(u,0,maxn);
if(n==0) break;
int x,y;
while (m--)
{
cin>>x>>y;
add(x,y);
add(y,x);
}
queue<int>q;
q.push(u[1]); //node
while (q.size())
{
int now=q.front();
q.pop();
for(int i=head[now];i;i=nxt[i]){
if(vis[i]==0){
vis[i]=1;
nodes[u[i]]=1;
nodes[v[i]]=1;
q.push(v[i]);
}
}
}
bool flag=true;
for(int i=1;i<=n;i++){
if(nodes[i]==0){
flag=false;
break;
}
}
if(flag) cout<<"YES\n";
else cout<<"NO\n";
}
}