보통 Controller에서 Dto를 받을 때는 @RequestBody를 주로 사용합니다.

그리고 File을 받을 때는 MultipartFile 객체를 사용하며, @RequestParam을 사용합니다.

 

하지만 File과 Dto를 같이 받기 위해서는 @RequestPart라는 어노테이션이 필요합니다.

File은 @RequestParam, Dto는 @RequestBody를 사용해서 받을려고 했지만 몇번을 시도해도 안되더라고요..

그래서 구글링을 통해 RequestPart라는 어노테이션을 찾아냈습니다.

 

우선 Controller입니다.

File과 Dto 모두 @RequestPart 어노테이션으로 받도록 합니다.

 

그리고 Dto인 UserInsertPostReq는 이렇게 구성되어 있습니다.

이전글 에서 사용했던 Dto와 동일합니다.

 

그리고 Controller에서 호출할 Service의 insertUser 메소드입니다.

파일을 저장할 경로를 지정한 후에 지정한 경로에 파일을 저장하고 DB에 유저 정보를 추가하는 로직입니다.

 

저는 이를 수행하기 위해 포스트맨을 사용하였습니다.

Key name은 @RequestPart 에서 value로 지정해준 name과 동일한 Key name으로 넣어줍니다.

이제 저기있는 Send를 눌러볼까요?

 

네 역시나 400에러가 발생합니다.

 

구글링을 통해 value에 json형식으로 넣는 방법을 알게되었고, 그대로 따라해보았습니다.

이런식으로 Key name은 userInsertPostReq, value는 json 방식으로 작성하였습니다.

다시 Send를 눌러보겠습니다.

 

이번에는 415 에러가 발생합니다..

 

한 두 시간 동안은 400, 415에러만 봤던것 같습니다.

 

이 에러들을 해결하기 위해 구글링을 해본 결과로는

여기서 Dto인 userInsertPostReq는 content type을 application/json으로 지정하면 해결할 수 있습니다.

userInsertPostReq의 content type을 application/json으로 지정한 후 Send를 누릅니다.

 

그럼 입력한 정보가 잘 들어가는 것을 확인할 수 있습니다.

 

File과 Dto를 같이 받아올 때 Key name과 content type 설정을 잘못하여 나온 에러 상황이었습니다.

이 방법 외에 다른 방법이 있는지는 잘 모르겠습니다. 더 많은 공부가 필요할 것 같습니다.

 

지금까지 단일 File과 Dto를 요청하는 것에 대해 알아보았고, 다수의 File과 Dto 요청에 관해서는 아래 링크에서 확인하시면 됩니다.

https://emoney96.tistory.com/375

 

Postman을 이용한 다수의 File, Dto 동시 Post 요청

https://emoney96.tistory.com/258 Postman을 이용한 MultipartFile, Dto 동시 Post요청 보통 Controller에서 Dto를 받을 때는 @RequestBody를 주로 사용합니다. 그리고 File을 받을 때는 MultipartFile 객체를 사..

emoney96.tistory.com

 

프로젝트 진행 중 JpaRepository에서 Pagenation을 적용한 Page객체를 받은 이후 Collections.sort로 정렬을 하였습니다.

하지만 이와 관련된 문제점 하나를 발견하게 되었고 포스팅으로 남길려고 합니다.

 

우선 db에 유저의 정보를 저장해줍니다.

profile_url은 file저장을 공부하면서 사용해본 것이며 이 글과는 상관 없는 file입니다.

내일쯤 file 저장관련 글을 포스팅할 예정입니다.

 

각 유저들의 점수(score)를 같이 저장해줍니다.

이 유저들을 score기준 내림차순으로 조회를 하는데 Pagenation을 적용시키려고 합니다.

 

 

UserRepository에서는 Page 객체로 리턴하는 findAll 메소드를 작성합니다.

 

UserServiceImpl에서 UserRepository의 findAll 메소드를 호출하는 findAllUser 메소드를 작성합니다.

userRepository.findAll로 Page객체를 가져오고, UserGetRes의 of 메소드에서 정렬을 진행합니다.

 

Pagenation을 적용했기 때문에 변수를 많이 사용하였지만 of 메소드의 정렬하는 부분이 핵심입니다.

Page객체를 가져와서 score기준 내림차순으로 정렬을 진행합니다.

 

그리고 Controller에서는 page와 size를 RequestParam으로 받아서 UserService의 findAllUser 메소드를 호출합니다.

 

이제 스웨거를 통해 테스트를 합니다.

확인할 페이지는 0페이지, 즉 첫번째 페이지를 조회하며 최대 3개의 데이터를 조회하려고 합니다.

 

결과는...

네.. 이렇게 나왔습니다.

 

원래 의도한 대로라면 score가 120인 id10부터 score가 100인 id2까지 나오는게 맞습니다.

여기서 확인해봐도 id는 10 -> 5 -> 2 순서대로 조회가 되어야합니다.

 

이 과정에서 제가 치명적인 실수를 한 것이 있습니다.

바로 Repository에서 Page객체를 가져온 이후에 정렬을 진행했다는 것입니다.

 

Page객체에 있는 데이터는 조회 가능한 모든 리스트가 있는것이 아니라 size만큼의 데이터만 있는 것이었습니다.

따라서 제가 Service에서 Repository를 호출할 때 Sort 기준을 아무것도 주지 않았기 때문에 먼저 추가된 데이터부터 size만큼 데이터가 조회된 것이었습니다.

 

그럼 이제 알맞게 수정을 해야겠죠?

우선 UserRepository의 findAll 메소드에 OrderByScore를 추가하거나 Pageable에 Sort를 추가합니다.

그 후에 UserGetRes의 정렬하는 부분을 지웁니다.

 

일단 UserGetRes의 of 메소드의 정렬부분을 지웁니다.

 

 

먼저 UserRepository의 findAll 메소드 수정하는 방법입니다.

findAllUsers로는 자동완성이 안뜨길래 findUsersByOrderByScoreDesc로 수정합니다.

뒤에 Desc를 안붙이면 default로 Asc가 적용됩니다.

 

 

다음은 UserService의 PageRequest에 Sort를 추가하는 방법입니다.

UserRepository에 있는 findAll 메소드는 그대로 두고 Sort를 추가합니다.

score 기준 DESC를 추가합니다.

 

 

둘 중 아무방법이나 사용한 다음 스웨거를 통해 테스트를 합니다.

그러면 이렇게 올바르게 조회를 할 수가 있습니다.

 

저는 두 번째 방법을 선호하기는 합니다만 두 방법 중 어떤 방법이 더 좋을지는 잘 모르겠습니다.

앞으로 로직을 구현할 때 생각이라는 것을 많이 해야겠다는 생각이 듭니다.

 

정렬을 적용하는 시점이 잘못되어 생긴 문제였습니다.

더미데이터를 작성하던 도중 겪었던 문제를 포스팅 하려고합니다.

 

우선 save는 JpaRepository에 내장되어있는 메소드입니다.

save가 수행하는 작업은 insert와 update 이렇게 두가지입니다.

insert와 update로 나뉘는 기준은 select를 했을 때 PK가 있으면 update, 없으면 insert입니다. (물론 null이어도 insert입니다.)

 

우선 User Entity를 작성합니다.

PK는 id이고 auto_increment 속성을 추가하였습니다.

 

그리고 UserRepository를 생성만 해줍니다.

어차피 JpaRepository 내장메소드인 save를 사용하므로 내용은 없습니다.

 

그리고 UserRepository에 대한 Test를 작성해주고 실행합니다.

 

어? save를 두번했으니 2L아닌가요??

심지어는 두번째로 save한 데이터로 덮어져 있습니다.

 

sql문 실행 로그를 확인해보았더니 insert를 했다가 update를 합니다.

 

사실 확인을 위해 save이후의 id를 확인해보았습니다.

 

여기서 insert 직후 id가 1로 출력이 되었습니다.

save(user)를 하였는데 user에 자동으로 insert된 row가 저장되는 모양입니다.

 

이를 해결하기 위해서는 두 번째 save를 하기 전에 id를 null로 바꿔주어야합니다.

user.setId(null);을 추가합니다.

 

이제 insert가 두 번 되었음을 확인할 수 있습니다.

 

db에도 잘 들어갔네요!

 

save를 하면 Entity 객체에 자동으로 값이 들어간다는 사실을 몰라서 겪었던 상황이었습니다.

@GeneratedValue는 @Id와 함께 쓰는 어노테이션이며 auto_increment와 같은 자동 생성 전략을 결정합니다.

 

JPA에서 복합키를 구현하기 위한 IdClass와 EmbeddedId를 복습하던 도중 @GeneratedValue도 함께 사용해보았습니다.

 

IdClass 사용

우선 Primary Key를 위한 UserId 클래스를 생성합니다.

 

그리고 User Entity를 생성합니다.

클래스선언 위에 @IdClass를 사용해줍니다.

 

이제 DB가 만들어지는지 실행을 해볼까요?

음~ 잘 만들어졌네요!

 

이제 User table에 데이터를 넣어봅시다.

데이터를 넣기 위해 Test를 작성하였습니다.

User 테이블은 auto_increment이므로 id는 1이됩니다.

 

하지만 에러가 떠버립니다.

 

 

EmbeddedId 사용

다음은 Embeddable 입니다.

우선 Primary Key를 위한 UserId 클래스를 생성합니다.

 

그리고 User Entity입니다.

PK 위에 @EmbeddedId를 사용합니다.

 

이번에는 auto_increment조차 생기지 않습니다.

다른 방법들도 시도해보았으나 모두 실패했습니다 ㅠ

 

 

결론

사실 제가 코드를 잘못 짠줄 알고 구글링을 여러번 시도했습니다.

https://infondgndg91.blogspot.com/2019/11/hibernate-composite-identifiers.html

 

Hibernate - Composite Identifiers @EmbeddedId @IdClass With @GeneratedValue is impossible

ndgndg91

infondgndg91.blogspot.com

그러던 중 이 블로그를 발견하였고, 이분도 어떤 커뮤니티에서 물어보셨던 것인지

@GeneratedValue를 @IdClass, @EmbeddedId와 함께 사용하는 것이 불가능하다는 답변을 받은것 같습니다.

 

앞으로 주의해서 사용해야 할 것 같습니다.

알고리즘 문제를 풀다보면 "소수점 2자리까지 출력하시오" 라고 하는 문제를 자주 보실겁니다..

이런 문제들을 매번 볼때마다 검색하는 저를 발견하였기에 정리합니다.

 

cout << fixed; 으로 소수점 자릿수를 고정합니다.

그 다음 cout.precision(n);으로 고정할 소수점 자리를 지정합니다.

이제 출력하시면 됩니다.

 

소수점을 3자리로 고정했으니 3자리까지만 출력됩니다.

 

 

다만 위의 사진처럼 소수점 아래에서 반올림을 해서 출력을 하니 이부분 조심해서 사용해야합니다.

'Etc' 카테고리의 다른 글

TypeScript 설치  (0) 2021.08.30
Windows 10 에서 WSL을 이용한 우분투 설치  (0) 2021.08.29
Java 문자열이 정수인지 확인  (0) 2021.06.01
localStorage를 이용한 데이터 저장  (0) 2021.05.11
Java 소수점 자리출력  (0) 2021.03.03

복합 키를 구현하기 위해서 두 가지 방법을 이용할 수 있습니다.

  1. IdClass 어노테이션 이용
  2. Embeddable 어노테이션 이용

IdClass 어노테이션은 https://emoney96.tistory.com/249 에 정리가 되어있으며,

이 글에서는 Embeddable 어노테이션 적용'만' 다룰 것입니다.

 

우선 @Embeddable을 적용할 Id전용 클래스를 생성합니다.

@IdClass와 다른 점은 @Embeddable을 붙인다는 점밖에 없습니다.

FollowId 클래스를 생성합니다.

 

Follow Entity 클래스에서 EmbeddedId 어노테이션을 적용한 FollowId 클래스 변수를 선언합니다.

 

그 다음 @MapsId 어노테이션을 이용하여 FollowId의 각 변수들과 매핑시켜주시면 됩니다.

여기서 주의할 점은

User 클래스에서 작성한 mappedBy의 이름과 Follow의 변수명이 같아야하고,

Follow 클래스에서 작성한 MapsId의 value와 FollowId의 변수명이 같아야합니다.

 

FollowId의 변수 fan을 fan1으로 변경했을 경우에도 실행은 됩니다.

하지만 table은 의도한대로 만들어지지 않는 것을 알 수 있습니다.

위의 결과는 fan1은 외래 키가 아니라 follow table의 순수 컬럼이자 기본 키가 되는 것이고,

fan은 외래 키가 맞지만 FollowId 클래스에 매핑할 "fan" 변수가 없어서 기본 키가 되지 못한 상황입니다.

 

 

복합 키를 구현하기 위해 @Id 어노테이션을 두개 사용했더니 에러가 발생했습니다 ㅠ

 

구글링 하다가 @Id를 한 클래스에 두개를 쓰면 안된다는 것을 알게되었고 복합 키 구현 방법을 찾아다녔습니다.

 

일단 복합 키 구현에는 두 가지 방법이 있습니다.

  1. IdClass 어노테이션 이용
  2. Embeddable 어노테이션 이용

저는 이 글에서 IdClass 어노테이션 적용'만' 다룰 것입니다.

(Embeddable은 몰라서 그래요.. 공부해서 포스팅 해보겠습니다...)

 

 

우선 @IdClass를 적용하기 위해 Id전용 클래스를 생성합니다.

저는 FollowId 클래스를 생성하였습니다.

 

그 다음 Entity 클래스에서 IdClass 어노테이션을 추가해서 작성해둔 Id전용 클래스를 적어두면 끝입니다!

 

여기서 주의할 점은

User 클래스에서 작성한 mappedBy의 이름과 Follow의 변수명, FollowId의 변수명

이 세가지가 모두 같아야합니다!

'Spring' 카테고리의 다른 글

Entity @GeneratedValue with @IdClass, @EmbeddedId  (2) 2021.08.06
Entity @Embeddable을 이용한 복합 키 구현  (0) 2021.08.01
Spring @RequestParam String[] 문제  (0) 2021.07.24
Spring JPA Pagenation  (0) 2021.07.24
Spring Optional.isPresent()  (0) 2021.07.15

Controller에서 Query String을 받아오기 위해 @RequestParam을 사용하였습니다.

@RequestParam을 이용하여 Sort객체 정보를 담기 위해 type은 String[]으로 지정하였습니다.

그럼 대략 이런식으로 쓸 수 있습니다.

 

그리고 스웨거를 이용하여 테스트를 합니다.

 

위에서부터 순서대로 sort.length, sort[0], sort[1] 입니다.

 

그럼 여기서 정렬조건을 하나만 넣어볼까요?

정렬조건을 title,desc으로 보냅니다.

 

??????? 갑자기 "title,desc"로 받아온게 아니라 split(",")으로 나눈것처럼 "title", "desc"로 받아왔습니다.

스프링에서는 ","로 나열된 String을 배열로 인식하여 자동으로 나눠준다고합니다.

하지만 저는 지금 상황에서 원하지 않습니다.. "title,desc" 이렇게 그대로 들어오기를 원합니다.

 

 

https://stackoverflow.com/questions/23695817/requestparam-array-mapping-issues/55251064

 

@RequestParam array mapping issues

I'm doing a REST service with Spring MVC framework. I have a method: @RequestMapping("/rest/{tableName}", method = RequestMethod.GET) public @ResponseBody CustomObject query( @PathVariable("

stackoverflow.com

다행히도 친구가 찾아준 이 링크에서 저와 같은 상황에 놓인 사람이 있었나봅니다.

 

밑의 댓글에서 준 코드를 적용하고싶은 컨트롤러에 붙이니 해결되었습니다.

이렇게 이 initBinder 메소드를 작성하는 것만으로 해결이 되었습니다.

 

아 편안하네요

'Spring' 카테고리의 다른 글

Entity @Embeddable을 이용한 복합 키 구현  (0) 2021.08.01
Entity @IdClass를 이용한 복합 키 구현  (0) 2021.07.29
Spring JPA Pagenation  (0) 2021.07.24
Spring Optional.isPresent()  (0) 2021.07.15
Spring 기본 세팅 (STS)  (0) 2021.06.12

말 그대로 페이징, 데이터를 페이지 단위로 나눠서 보여주는 작업입니다.

이를 위해 JPA에서는 페이지 정보와 정렬 기준으로 페이징 처리를 하며 PageRequest, Pageable, Sort 객제를 사용합니다.

1
2
3
4
@Repository
public interface ConferenceRepository extends JpaRepository<Conference, Long> {
    Page<Conference> findAll(Pageable pageable);
}
cs

Repository 구성입니다.

return type을 Page 객체로 감싸줍니다.

Service에서 PageRequest 객체를 넘겨주면 Repository에서 Pageable 객체로 받습니다.

Pageable 객체에는 페이징 정보와 정렬 기준을 모두 포함하므로 전달받는 파라미터에 반드시 포함되어야합니다.

 

1
2
3
4
5
6
7
8
9
10
@Service
public class ConferenceServiceImpl implements ConferenceService {
    @Override
    public ConferenceFindAllGetRes findAllConference(int page, int size) {
        Sort sorts = Sort.by(Sort.Direction.DESC, "id");
        PageRequest pageRequest = PageRequest.of(page, size, sorts);
    
        return ConferenceFindAllGetRes.of(conferenceRepository.findAll(pageRequest), pageRequest, sorts);
    }
}
cs

Repository에서는 페이징 정보를 Pageable로 받지만 Service에서 호출 시 보낼 페이징 정보는 PageRequest 객체입니다.

딱 Request만 봐도 요청 잘하게 생겼죠?

PageRequest.of(page, size, sorts);

page: 현재 페이지 (코드에서 첫 페이지는 0입니다.)

size: 페이지에서 출력할 데이터의 갯수

sorts: 정렬기준, 방법 (ex. id 기준 asc or desc)

 

그럼 이런식으로 정렬기준에 맞게 출력이 됩니다!

이거를 이제 findByTitle이나 findByConferenceCategoryId와 같은 메소드에도 적용할 수 있습니다

스프링에서 Optional 객체에 get() 메소드를 사용하여 안에 있는 객체를 가져올 수 있습니다.

하지만 비어있는 Optional 객체를 대상으로 get() 메소드를 사용할 경우 에러가 발생합니다.

 

따라서 isPresent()객체를 사용하여 객체 존재여부를 확인 후에 가져오도록 해야합니다.

 

 

ex)

1
User user = userRepositorySupport.findUserByUserId(userId).get();
cs

=> findUserByUserId에서 객체를 못 가져왔을 시 에러 발생

 

1
2
3
4
5
6
Optional<User> user = userRepositorySupport.findUserByUserId(userId);
        
if(user.isPresent())
    return user.get();
else
    return null;
cs

=> isPresent() 메소드로 사전에 확인함으로 문제 해결

'Spring' 카테고리의 다른 글

Entity @Embeddable을 이용한 복합 키 구현  (0) 2021.08.01
Entity @IdClass를 이용한 복합 키 구현  (0) 2021.07.29
Spring @RequestParam String[] 문제  (0) 2021.07.24
Spring JPA Pagenation  (0) 2021.07.24
Spring 기본 세팅 (STS)  (0) 2021.06.12

https://www.acmicpc.net/problem/17090

 

17090번: 미로 탈출하기

크기가 N×M인 미로가 있고, 미로는 크기가 1×1인 칸으로 나누어져 있다. 미로의 각 칸에는 문자가 하나 적혀있는데, 적혀있는 문자에 따라서 다른 칸으로 이동할 수 있다. 어떤 칸(r, c)에 적힌 문

www.acmicpc.net

 

https://emoney96.tistory.com/24

 

boj 1103 게임

https://www.acmicpc.net/problem/1103 1103번: 게임 줄에 보드의 세로 크기 N과 가로 크기 M이 주어진다. 이 값은 모두 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 보드의 상태가 주어진다. 쓰여

emoney96.tistory.com

dfs + dp 문제이며 위의 문제와 비슷한 방법으로 해결하였습니다.

 

대신 게임 문제는 방향이 정해져있지 않아서 4방향 모두 확인해야하지만 이 문제는 1방향만 확인하면 되는 문제입니다.

현재 좌표의 방향으로 이동하면서 맵 밖으로 나가면 1을 리턴, visit으로 사이클을 체크해서 사이클이 발생했으면 0을 리턴합니다.

 

N * M번 모두 돌려가면서 ans를 구하였습니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static char list[][] = new char[510][510];
    static boolean visit[][] = new boolean[510][510];
    static int dp[][] = new int[510][510];
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static int N, M, ans;
 
    static int dfs(int x, int y) {
        if (visit[x][y])
            return 0;
        visit[x][y] = true;
 
        if (dp[x][y] != -1)
            return dp[x][y];
 
        int d = 0;
        if (list[x][y] == 'D')
            d = 1;
        else if (list[x][y] == 'R')
            d = 0;
        else if (list[x][y] == 'U')
            d = 3;
        else
            d = 2;
 
        int nx = x + direct[d][0];
        int ny = y + direct[d][1];
 
        if (nx < 0 || nx >= N || ny < 0 || ny >= M)
            dp[x][y] = 1;
        else {
            dp[x][y] = dfs(x + direct[d][0], y + direct[d][1]);
            visit[nx][ny] = false;    
        }
 
        return dp[x][y];
    }
 
    static void func() {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (dp[i][j] != -1) {
                    ans += dp[i][j];
                    continue;
                }
                ans += dfs(i, j);
                visit[i][j] = false;
            }
        }
 
        System.out.println(ans);
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            list[i] = st.nextToken().toCharArray();
            Arrays.fill(dp[i], -1);
        }
 
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
    }
}
cs

'algorithm > dp' 카테고리의 다른 글

boj 20500 Ezreal 여눈부터 가네 ㅈㅈ  (0) 2022.01.01
boj 1135 뉴스 전하기  (0) 2021.11.15
boj 1648 격자판 채우기  (0) 2021.06.22
boj 14700 넴모넴모 (Hard)  (0) 2021.06.22
boj 1311 할 일 정하기 1  (0) 2021.06.21

https://www.acmicpc.net/problem/20040

 

20040번: 사이클 게임

사이클 게임은 두 명의 플레이어가 차례대로 돌아가며 진행하는 게임으로, 선 플레이어가 홀수 번째 차례를, 후 플레이어가 짝수 번째 차례를 진행한다. 게임 시작 시 0 부터 n − 1 까지 고유한

www.acmicpc.net

코테를 자바로 해야하기 때문에 오랜만에 자바로 리뷰를 합니다...

오랜만에 자바로 알고리즘 하니까 어색하네요

 

기본적인 union-find를 활용해볼 수 있는 문제입니다.

 

u와 v 노드를 연결 할 때 사이클이 생기는 경우는 u의 루트와 v의 루트가 같을 때입니다.

따라서 union-find 과정 중에 u의 루트와 v의 루트가 같은지 확인하여 같으면 true, 다르면 false를 리턴해주었고,

 

맨 처음 true를 받아온 경우에만 ans에 갱신 해주었습니다.

(사이클이 생기지 않는 경우도 있기 때문에 생각을 해주어야합니다.)

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int parent[] = new int[500001];
    static int N, M, ans;
 
    static int find(int v) {
        if (parent[v] == v)
            return v;
        return parent[v] = find(parent[v]);
    }
 
    static boolean union(int x, int y) {
        int a = find(x);
        int b = find(y);
 
        if (a == b)
            return true;
        parent[b] = a;
        return false;
    }
 
    static void init() {
        for (int i = 0; i < N; i++)
            parent[i] = i;
    }
 
    static void input() throws Exception {
        int u, v;
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        init();
        for (int i = 1; i <= M; i++) {
            st = new StringTokenizer(br.readLine());
            u = Integer.parseInt(st.nextToken());
            v = Integer.parseInt(st.nextToken());
 
            if (union(u, v) && ans == 0)
                ans = i;
        }
 
        System.out.println(ans);
    }
 
    public static void main(String[] args) throws Exception {
        input();
    }
}
cs

'algorithm > Union-Find' 카테고리의 다른 글

boj 1043 거짓말  (0) 2021.04.05
boj 10775 공항  (0) 2021.03.17
boj 4195 친구 네트워크  (0) 2021.03.17
boj 1976 여행 가자  (0) 2021.03.17
boj 1717 집합의 표현  (0) 2021.02.06

+ Recent posts