파이썬 알고리즘 081 | 회장뽑기(플로이드-워샬 응용)

Yunny.Log ·2021년 1월 23일
0

Algorithm

목록 보기
84/318
post-thumbnail

81. 회장뽑기(플로이드-워샬 응용)

월드컵축구의 응원을 위한 모임에서 회장을 선출하려고 한다. 이모임은 만들어진지 얼마 되지
않았기 때문에 회원사이에 서로 모르는 사람도 있지만, 몇 사람을 통하면 서로 모두 알 수 있
다.
각 회원은 다른 회원들과 가까운 정도에 따라 점수를 받게 된다.
예를 들어 어느 회원이 다른 모든 회원과 친구이면, 이 회원의 점수는 1점이다. 어느 회원의
점수가 2점이면, 다른 모든 회원이 친구이거나, 친구의 친구임을 말한다. 또한, 어느 회원의
점수가 3점이면, 다른 모든 회원이 친구이거나, 친구의 친구이거나, 친국의 친구의 친구임을
말한다.4점, 5점등은 같은 방법으로 정해진다.
각 회원의 점수를 정할 때 주의할 점은 어떤 두 회원이 친구 사이이면서 동시에 친구의 친구
사이이면, 이 두 사람은 친구사이라고 본다. 회장은 회원들 중에서 점수가 가장 작은 사람이
된다.
회장의 점수와 회장이 될 수 있는 모든 사람을 찾는 프로그램을 작성하시오.
▣ 입력설명
입력의 첫째 줄에는 회원의 수가 있다.
단, 회원의 수는 50명을 넘지 않는다. 둘째 줄 이후로는 한 줄에 두 개의 회원번호가 있는데,
이것은 두 회원이 서로 친구임을 나타낸다. 회원번호는 1부터 회원의 수만큼 번호가 붙어있다.
마지막 줄에는 -1이 두 개 들어있다
▣ 출력설명
첫째 줄은 회장 후보의 점수와 회장후보 수를 출력하고 두 번째 줄은 회장 후보를 모두 출력
한다.
▣ 입력예제 1
5
1 2
2 3
3 4
4 5
2 4
5 3
-1 -1
▣ 출력예제 1
2 3
2 3 4
출처 : 한국정보올림피아드

<내 풀이>

=> 밑과 같이 출력된다, 어떤 부분이 누락된 것일까
[50, 50, 1, 2, 2, 3]

[50, 50, 50, 1, 1, 2]

[50, 50, 50, 3, 1, 2]

[50, 50, 50, 2, 3, 1]

[50, 50, 50, 1, 2, 3]
===> 바로 2-3 이 친구면 2->3 방향이 1인 동시에 3->2 방향도 1이라는 사실을 누락하였음. 문제에 방향이 정확히 표기되지 않은 경우에도 내가 잘 추측해서 해야함
===> 방향을 표기해주면
[50, 50, 50, 50, 50, 50]

[50, 2, 1, 2, 2, 3]

[50, 1, 2, 1, 1, 2]

[50, 2, 1, 2, 1, 1]

[50, 2, 1, 1, 2, 1]

[50, 3, 2, 1, 1, 2]

이렇게 나온다, 라인당 max값이 자신의 점수이다
따라서 1번애 : 3점 / 2번애 : 2점 / 3번애 : 2점 / 4번애 : 2점 / 5번애 : 3점/
이므로 회장 후보는 이 중에서 min 값을 가진 2,3,4
=====> 근데 누락한 부분 있었다, 자신이 자신에게 가는 경우는 0처리 해주어야함


minn=1000
if __name__=='__main__' :
    n=int(input())
    dis=[[50]*(n+1) for _ in range(n+1)]
    while True:
        a,b= map(int,input().split())
        if a==-1 and b==-1 :
            break
        dis[a][b]=1 #a,b직접 친구
    for k in range(1,n+1) :
        for i in range(1,n+1) :
            for j in range(1,n+1) :
                dis[i][j]=min(dis[i][j], dis[i][k]+dis[k][j])
    for i in range(1,n+1) :
        for j in range(1,n+1) :
            if dis[i][j]<minn:
                minn=dis[i][j]
for i in dis :
    print(i)
print(minn)

(2) 최종 풀이

cnt=0
res=[]
ress=[]
if __name__=='__main__' :
    n=int(input())
    dis=[[50]*(n+1) for _ in range(n+1)]
    for i in range(1,n+1) : ###
        dis[i][i]=0 ### 이 부분을 추가해줬어야 한다
    while True:
        a,b= map(int,input().split())
        if a==-1 and b==-1 :
            break
        dis[a][b]=1 #a,b직접 친구
        dis[b][a]=1 #이것도 추가해줘야 한다ㅠ a-b가 친구라면 b-a도 친구..
    for k in range(1,n+1) :
        for i in range(1,n+1) :
            for j in range(1,n+1) :
                dis[i][j]=min(dis[i][j], dis[i][k]+dis[k][j])

for i in range(1,n+1) :
    maxx=-1
    for j in range(1,n+1) :
        if dis[i][j]>maxx:
            maxx=dis[i][j]
    res.append(maxx)

for k,v in enumerate(res) :
    if v==min(res):
        ress.append(k+1)

print(min(res), len(ress))    
for i in ress:
    print(i, end=' ')   

<풀이>


if __name__=="__main__":
    n=int(input())
    dis=[[100]*(n+1) for _ in range(n+1)]
    for i in range(1, n+1):
        dis[i][i]=0
    while True:
        a, b=map(int, input().split())
        if a==-1 and b==-1:
            break
        dis[a][b]=1
        dis[b][a]=1

    for k in range(1, n+1):
        for i in range(1, n+1):
            for j in range(1, n+1):
                dis[i][j]=min(dis[i][j], dis[i][k]+dis[k][j])

    res=[0]*(n+1)
    score=100
    for i in range(1, n+1):
        for j in range(1, n+1):
            res[i]=max(res[i], dis[i][j])
        score=min(score, res[i])
    out=[]
    for i in range(1, n+1):
        if res[i]==score:
            out.append(i)
    print("%d %d" %(score, len(out)))
    for x in out:
        print(x, end=' ')

<반성점>

  • 자기한테서 자기갈 때는 미리 dis에 0,0 입력해두기
  • 바로 2-3 이 친구면 2->3 방향이 1인 동시에 3->2 방향도 1이라는 사실을 누락하였음. 문제에 방향이 정확히 표기되지 않은 경우에도 내가 잘 추측해서 해야함

<배운 점>

<2차 내 풀이>


n=int(input())
a=[[50]*(n+1) for _ in range(n+1)]

while True:
    i,j=map(int,input().split())
    if i!=-1 and j!=-1: 
        a[i][j]=1
        a[j][i]=1
    else : 
        break
for k in range(1,n+1) :
    for i in range(1,n+1) :
        for j in range(1,n+1) :
            a[i][j]=min(a[i][j], a[i][k]+a[k][j])
m=[]
for i in range(1,n+1):
    max=0
    for j in range(1,n+1) :
        if a[i][j]<50 and a[i][j]>max:
            max=a[i][j]
    m.append(max)
kk=[]
cnt=0
mini=10000
for i in range(1,len(m)):
    if m[i]==min(m):
        cnt+=1
        kk.append(i+1)

print(min(m),cnt)
for i in kk:
    print(i, end=' ')

0개의 댓글