问题描述:
共有N个樱桃,目前N个樱桃中有M条黑色糖线(黑色表示含糖量为1个单位),为使所有樱桃连在一起(最小生成树的感觉),可能还需红色糖线(红色含糖量为2个单位),问最终最少的含糖量。(原链接:https://codingcompetitions.withgoogle.com/kickstart/round/0000000000050edb/0000000000170721)
首先是我自己的代码
感觉比较野路子,本地试了很多case都可以通过,但submit attempt 还是runtime error。
import numpy as np
def DG(conn1,i,A,k):
newk=np.concatenate((np.argwhere(conn1[:,i]==1),np.argwhere(conn1[i,:]==1)),axis=0)
if newk.size>0:
newk=newk.tolist()
newk=sum(newk,[])
k=k+newk
# vertex conencted to i
if len(k)!=0:
for aa in k: #
coco=conn1[aa,range(0,A)]
if 1 in coco:
return 1
else:
conn2=conn1.copy()
conn2[aa,i]=0
k.pop(0)
return DG(conn2,aa,A,k) # vertex connect to aa
else:
return 2
def solve(N,M):
conn=np.zeros((N,N))
for i in range(0,M):
v1,v2=[int(s) for s in input().split(" ")]
v1,v2=sorted([v1,v2])
conn[v2-1,v1-1]=1 # v1<v2
degree=np.zeros((N,1))
for i in range(1,N):
temp=conn[i,range(0,i)]
if 1 in temp: # directly connect to 0:i
degree[i]=1
else: # indirectly connect to 0:i
conn1=conn.copy()
degree[i]=DG(conn1,i,i,[])
return int(np.sum(degree))
case=int(input())
for k in range(1,case+1):
N,M=[int(s) for s in input().split(" ")]
degree=solve(N,M)
print("Case #{}: {}".format(k, degree))
然后是把大神的C++改写成了python的kruscal算法
真的是简洁有力
import numpy as np
def find(x):
if f[x]!=x:
f[x]=find(f[x]) # 寻找祖先节点
return f[x]
case=int(input())
for k in range(1,case+1):
N,M=[int(s) for s in input().split(" ")]
ans=(N-1)*2 # 不存在环路下的最小生成树 按每条边都是红色糖线来计算,输入的边为黑色糖线
f=list(range(N))
for i in range(M):
x,y=[int(s) for s in input().split(" ")]
x=x-1
y=y-1
u=find(x) # 寻找祖先节点
v=find(y)
if u==v: # 有相同的祖先节点,再连接即为环路,即该边不属于最小生成树,跳过该边,进行下一组边的判断
continue
f[u]=v
ans=ans-1
print("Case #{}: {}".format(k, ans))