解析
本题两个知识点
1. 找到找到所有的找到所以的子集
2. 找到本次图的所有顶点(因为删除了部分边,部分点可能也被删除)
1,通过二进制码(00…0)-(11…1),1表示有这条边,0表示没有,用递归求,结束条件:为全1,用全局变量t=6记录,每次有变为0的+1,变为1的-1即可(或者在递归加一个参数)。状态转移:每次递归都加1(即vis[0]+1,用判断模拟),即如果当前位置为1则进1。
2,通过选出的边,确定本次图的所有的顶点(从而可以确定此图连通所需的最少边)
package 蓝桥杯2020第二场;
import java.util.*;
class e{
int x,y;
public e(int x,int y) {
this.x=x;
this.y=y;
}
}
public static void main(String[] args) {
e ed[]=new e[10];
ed[0]=new e(1,2);
ed[1]=new e(2,3);
ed[2]=new e(3,4);
ed[3]=new e(4,5);
ed[4]=new e(5,6);
ed[5]=new e(6,3);
ed[6]=new e(6,1);
int total=0;
int num=0;
for (int k = 0;; k++) {
dfs(0);//每次寻找一个子集,共找2^n-1次,全0不做计算
if(flag==1) break;
int v[]=new int[7];
for (int i = 1; i <=6; i++) {//初始化
v[i]=i;
}
int s=0,t5=0;//s表示节点个数
int a[]=new int[7];
for (int i = 0; i < 7; i++) {
if(vis[i]==1) {
t5=ed[i].x;
if(a[t5]==0) s++;
a[t5]=1;
t5=ed[i].y;
if(a[t5]==0) s++;
a[t5]=1;
}
}
for (int i = 0; i < a.length; i++) {
a[i]=0;
}
s-=1;//所需最少的边
for (int i = 0; i < 7; i++) {
if(vis[i]==1) {
int t1=find(ed[i].x,v);
int t2=find(ed[i].y,v);
if(t1!=t2) {
join(t1,t2,v);
s--;
if(s==0) break;
}
}
}
if(s==0) total++;
}
System.out.println(total);
}
private static void join(int t1, int t2,int[] v) {//集合合拼
if(t1>t2) v[t1]=t2;
else v[t2]=t1;
}
private static int find(int x,int[] v) {
int r=x;
while(v[r]!=r) {//找到队长
r=v[r];
}
int p=x,q=0;
while(v[p]!=p) {//压缩
q=v[p];
v[p]=r;
p=q;
}
return r;
}
private static void dfs(int k) {
if(t==0) {flag=1;return;}
if(vis[k]==1) {
vis[k]=0;
t++;
dfs(k+1);
}else {
vis[k]=1;
t--;
}
}
}