SlideShare a Scribd company logo
1 of 28
SCPC 1회 본선 - 트리
박현민
2017-07-18 1
목차
 문제
 배경 지식
 해법
 코드
 참고 문헌
2017-07-18 2
문제
Chapter1
2017-07-18 3
2017-07-18 4
문제
2017-07-18 5
문제 (Cont’d)
배경 지식
Chapter2
2017-07-18 6
 Laplacian matrix L
 Degree matrix D
 Adjacency matrix A
 L = D – A
 Li,j
– deg(vi) if i = j
– -1 if i ≠ j and vi is adjacent to vj
– 0 otherwise
2017-07-18 7
Laplacian matrix
 Incidence matrix I
 Ii,j
– 1 if ej ends in i
– -1 if ej starts in i
– 0 otherwise
 L = I × IT
2017-07-18 8
Laplacian matrix (Cont’d)
 L’s i, j minor matrix Mi,j
 |ST| = (L’s (i,j)-cofactor) = (-1)i+j × det(Mi,j)
2017-07-18 9
Kirchhoff’s matrix tree theorem
 Ii,j
– xw(i,j) if ej ends in i
– -xw(i,j) if ej starts in i
– 0 otherwise
 L = I × IT
 Li,j
– Σkxw(i,k) if i = j
– -xw(i,j) if i ≠ j and vi is adjacent to vj
– 0 otherwise
2017-07-18 10
Extension towards MST
 (-1)i+j × det(Mi,j) = Σw|STw| × xw
 |MST| = minw|STw|
2017-07-18 11
Extension towards MST (Cont’d)
 Gaussian elimination
– B is a matrix obtained by multiplying a row of A by some
non-zero constant ß
• det(A)= ß-1 * det(B)
– B is a matrix obtained by adding a multiple of one row to
another row in A
• det(A)= det(B)
 Row echelon form matrix R
 det(R) = ΠiRi,i
2017-07-18 12
Determinant with O(n3)
 1000000007 is prime
 ap-1 ≡ 1 (mod p)
 a-1 ≡ ap-2 (mod p)
 O(log p)
2017-07-18 13
Inverse in modulo operation
해법
Chapter3
2017-07-18 14
 Matrix M
 For i in 1 ~ n
– For j in i + 1 ~ n
• // Shouldmake Mj,i to 0
• (Rowj) := Mi,i × (Rowj) – Mj,i × (Rowi)
• det = Mi,i
-1 × det
 // M is now in row echelon form
 det = det × ΠiMi,i
2017-07-18 15
Determinant with O(n3) (Cont’d)
 앞에서 소개한 다항식 계산을 통해 MST를 구하는 방법은
구현이 까다로울 것으로 예상됨
 모든 간선을 가중치로 정렬
 어떤 가중치 값에 대해 그 값으로만 구성되는 신장트리의
수 계산
– 그 가중치 값보다 작은 모든 간선은 이미 연결된 것으로 처리
 모두 곱하여 최소신장트리의 수 계산
2017-07-18 16
최소신장트리
 모든 간선을 가중치로 정렬한 후 상한을 결정
– 상한을 늘려가며 모두 연결되었는지 확인
 상한 이내의 간선만 선택
– 간선의 가중치는 더 이상 필요하지 않음
 선택된 간선들만으로 이뤄진 신장트리의 수 계산
2017-07-18 17
최소병목신장트리
코드
Chapter4
2017-07-18 18
#pragma warning(disable:4786)
#include<iostream>
using namespace std;
#include<algorithm>
#include<set>
#include<vector>
#include<memory.h>
struct S
{
int x,y,v;
bool operator()(S a,S b)
{
return a.v<b.v;
}
}a[1010];
int t,n,m,d[110][110],p[110],c[110],cnt;
set<int> s;
vector<pair<int,int> > v[110];
int getDivisor(int a)
{
int i;
long long b[40]={a},ret=1;
for(i=1;i<=30;++i)b[i]=(b[i-1]*b[i-1])%1000000007;
for(i=0;i<=30;++i)if((1<<i)&1000000005)ret=(ret*b[i]+1000000007)%1000000007;
return ret;
}
int countSpanningTree(int n)
{
int i,j,k,t;
long long ret=1;
for(i=2;i<=n;++i)
{
if(d[i][i]==0)continue;
for(j=i+1;j<=n;++j)
{
if(d[j][i]==0)continue;
t=d[j][i];
for(k=i;k<=n;++k)d[j][k]=d[i][i]*d[j][k]-t*d[i][k];
ret=(ret*getDivisor(d[i][i]))%1000000007;
}
ret=(ret*d[i][i]+1000000007)%1000000007;
}
return ret;
}
int uf(int v)
{
if(p[v]==v)return v;
else return p[v]=uf(p[v]);
}
void dfs(int p,int mxv)
{
int i;
c[p]=cnt;
for(i=0;i<v[p].size();++i)if(!c[v[p][i].first]&&v[p][i].second<=mxv)dfs(v[p][i].first,mxv);
}
inline int mn2(int a,int b)
{
if(a>b)return b;
else return a;
}
int main()
{
int i,j,k,l,next;
long long out;
set<int>::iterator it;
cin.sync_with_stdio(false);
cin>>t;
for(i=1;i<=t;++i)
{
cin>>n>>m;
for(j=1;j<=n;++j)v[j].clear();
for(j=1;j<=m;++j)
{
cin>>a[j].x>>a[j].y>>a[j].v;
v[a[j].x].push_back(make_pair(a[j].y,a[j].v));
v[a[j].y].push_back(make_pair(a[j].x,a[j].v));
}
out=1;
sort(&a[1],&a[m+1],S());
for(j=1;j<=m;j=next)
{
for(next=j+1;next<=m;++next)if(a[next].v!=a[j].v)break;
memset(c,0,sizeof(c));
cnt=0;
for(k=1;k<=n;++k)
{
if(c[k])continue;
for(l=0;l<v[k].size();++l)if(v[k][l].second<a[j].v)break;
if(l<v[k].size())
{
++cnt;
dfs(k,a[j].v-1);
}
}
s.clear();
for(k=j;k<next;++k)
{
s.insert(a[k].x);
s.insert(a[k].y);
}
for(it=s.begin();it!=s.end();++it)if(!c[*it])c[*it]=++cnt;
memset(d,0,sizeof(d));
for(k=j;k<next;++k)
{
d[c[a[k].x]][c[a[k].x]]++;
d[c[a[k].y]][c[a[k].y]]++;
d[c[a[k].x]][c[a[k].y]]--;
d[c[a[k].y]][c[a[k].x]]--;
}
out=(out*countSpanningTree(cnt)+1000000007)%1000000007;
}
for(j=1;j<=n;++j)p[j]=j;
for(j=1;j<=m;j=next)
{
for(next=j+1;next<=m;++next)if(a[next].v!=a[j].v)break;
for(k=j;k<next;++k)p[a[k].x]=uf(a[k].y);
for(k=1;k<=n;++k)if(uf(k)!=uf(1))break;
if(k>n)continue;
}
memset(d,0,sizeof(d));
for(j=1;j<next;++j)
{
d[a[j].x][a[j].x]++;
d[a[j].y][a[j].y]++;
d[a[j].x][a[j].y]=-1;
d[a[j].y][a[j].x]=-1;
}
cout<<"Case #"<<i<<endl<<(int)out<<" "<<countSpanningTree(n)<<endl;
}
return 0;
}
2017-07-18 19
전체 코드
int getDivisor(int a)
{
int i;
long long b[40]={a},ret=1;
for(i=1;i<=30;++i)b[i]=(b[i-1]*b[i-1])%1000000007;
for(i=0;i<=30;++i)if((1<<i)&1000000005)ret=(ret*b[i]
+1000000007)%1000000007;
return ret;
}
2017-07-18 20
Inverse in modulo operation (Cont’d)
intcountSpanningTree(intn)
{
inti,j,k,t;
longlongret=1;
for(i=2;i<=n;++i)
{
if(d[i][i]==0)continue;
for(j=i+1;j<=n;++j)
{
if(d[j][i]==0)continue;
t=d[j][i];
for(k=i;k<=n;++k)d[j][k]=d[i][i]*d[j][k]-t*d[i][k];
ret=(ret*getDivisor(d[i][i]))%1000000007;
}
ret=(ret*d[i][i]+1000000007)%1000000007;
}
returnret;
}
2017-07-18 21
Determinant with O(n3) (Cont’d)
for(j=1;j<=m;j=next)
{
for(next=j+1;next<=m;++next)if(a[next].v!=a[j].v)break;
memset(c,0,sizeof(c));
cnt=0;
for(k=1;k<=n;++k)
{
if(c[k])continue;
for(l=0;l<v[k].size();++l)if(v[k][l].second<a[j].v)break;
if(l<v[k].size())
{
++cnt;
dfs(k,a[j].v-1);
}
}
s.clear();
for(k=j;k<next;++k)
{
s.insert(a[k].x);
s.insert(a[k].y);
}
for(it=s.begin();it!=s.end();++it)if(!c[*it])c[*it]=++cnt;
memset(d,0,sizeof(d));
for(k=j;k<next;++k)
{
d[c[a[k].x]][c[a[k].x]]++;
d[c[a[k].y]][c[a[k].y]]++;
d[c[a[k].x]][c[a[k].y]]--;
d[c[a[k].y]][c[a[k].x]]--;
}
out=(out*countSpanningTree(cnt)+1000000007)%1000000007;
}
// answer = out
2017-07-18 22
최소신장트리
for(j=1;j<=n;++j)p[j]=j;
for(j=1;j<=m;j=next)
{
for(next=j+1;next<=m;++next)if(a[next].v!=a[j].v)break;
for(k=j;k<next;++k)p[a[k].x]=uf(a[k].y);
for(k=1;k<=n;++k)if(uf(k)!=uf(1))break;
if(k>n)continue;
}
memset(d,0,sizeof(d));
for(j=1;j<next;++j)
{
d[a[j].x][a[j].x]++;
d[a[j].y][a[j].y]++;
d[a[j].x][a[j].y]=-1;
d[a[j].y][a[j].x]=-1;
}
//answer=countSpanningTree(n)
2017-07-18 23
최소병목신장트리
참고 문헌
Appendix
2017-07-18 24
 https://en.wikipedia.org/wiki/Laplacian_matrix
 https://en.wikipedia.org/wiki/Kirchhoff%27s_theorem
 https://ko.wikipedia.org/wiki/%EB%9D%BC%ED%94%8C
%EB%9D%BC%EC%8A%A4_%EC%A0%84%EA%B0%9
C
 Konstantin Pieper(2008), “The Number of Spanning Trees
in a Graph”, pp.4-8,
http://wwwmayr.in.tum.de/konferenzen/Jass08/courses/
1/pieper/Pieper_Paper.pdf
 https://stackoverflow.com/a/38156436
2017-07-18 25
참고 문헌
Q&A
2017-07-18 26
감사합니다
2017-07-18 27
이 프레젠테이션은
https://www.slideshare.net/525hm/170718-scpc-1
에서 다시 보실 수 있습니다
2017-07-18 28

More Related Content

More from Hyeonmin Park

More from Hyeonmin Park (20)

[16.05.11] KIST 청년 소프트웨어 프로젝트 @ 경기과학고등학교
[16.05.11] KIST 청년 소프트웨어 프로젝트 @ 경기과학고등학교[16.05.11] KIST 청년 소프트웨어 프로젝트 @ 경기과학고등학교
[16.05.11] KIST 청년 소프트웨어 프로젝트 @ 경기과학고등학교
 
[15.10.07] 슈퍼컴퓨터를 이용한 안드로이드 어플리케이션의 정적 분석
[15.10.07] 슈퍼컴퓨터를 이용한 안드로이드 어플리케이션의 정적 분석[15.10.07] 슈퍼컴퓨터를 이용한 안드로이드 어플리케이션의 정적 분석
[15.10.07] 슈퍼컴퓨터를 이용한 안드로이드 어플리케이션의 정적 분석
 
[15.08.19] 존경하는 인물
[15.08.19] 존경하는 인물[15.08.19] 존경하는 인물
[15.08.19] 존경하는 인물
 
[15.09.09] Alphabet
[15.09.09] Alphabet[15.09.09] Alphabet
[15.09.09] Alphabet
 
[14.07.25] KENNYSOFT - 야구심판
[14.07.25] KENNYSOFT - 야구심판[14.07.25] KENNYSOFT - 야구심판
[14.07.25] KENNYSOFT - 야구심판
 
[14.07.09] STAC 2014
[14.07.09] STAC 2014[14.07.09] STAC 2014
[14.07.09] STAC 2014
 
[14.05.02] 5/2 (금)
[14.05.02] 5/2 (금)[14.05.02] 5/2 (금)
[14.05.02] 5/2 (금)
 
[15.08.07] 슈퍼컴퓨터를 이용한 안드로이드 어플리케이션의 정적 분석
[15.08.07] 슈퍼컴퓨터를 이용한 안드로이드 어플리케이션의 정적 분석[15.08.07] 슈퍼컴퓨터를 이용한 안드로이드 어플리케이션의 정적 분석
[15.08.07] 슈퍼컴퓨터를 이용한 안드로이드 어플리케이션의 정적 분석
 
[15.05.22] 정보 전달하는 글 쓰고 읽기
[15.05.22] 정보 전달하는 글 쓰고 읽기[15.05.22] 정보 전달하는 글 쓰고 읽기
[15.05.22] 정보 전달하는 글 쓰고 읽기
 
[15.05.01] Bèzier Curve
[15.05.01] Bèzier Curve[15.05.01] Bèzier Curve
[15.05.01] Bèzier Curve
 
[15.04.27] 최고가격제와 최저가격제
[15.04.27] 최고가격제와 최저가격제[15.04.27] 최고가격제와 최저가격제
[15.04.27] 최고가격제와 최저가격제
 
[15.04.20] WEEK9_박현민_주원철
[15.04.20] WEEK9_박현민_주원철[15.04.20] WEEK9_박현민_주원철
[15.04.20] WEEK9_박현민_주원철
 
[15.03.12] 일차변환
[15.03.12] 일차변환[15.03.12] 일차변환
[15.03.12] 일차변환
 
[15.03.09] 행렬
[15.03.09] 행렬[15.03.09] 행렬
[15.03.09] 행렬
 
[15.02.05] 타일 채우기 4
[15.02.05] 타일 채우기 4[15.02.05] 타일 채우기 4
[15.02.05] 타일 채우기 4
 
[14.12.02] ABCDEF
[14.12.02] ABCDEF[14.12.02] ABCDEF
[14.12.02] ABCDEF
 
[14.11.26] 아이스크림과 의문의 약
[14.11.26] 아이스크림과 의문의 약[14.11.26] 아이스크림과 의문의 약
[14.11.26] 아이스크림과 의문의 약
 
[14.11.22] 모바일 어플리케이션의 정적 분석을 통한 개인정보 유출 차단
[14.11.22] 모바일 어플리케이션의 정적 분석을 통한 개인정보 유출 차단[14.11.22] 모바일 어플리케이션의 정적 분석을 통한 개인정보 유출 차단
[14.11.22] 모바일 어플리케이션의 정적 분석을 통한 개인정보 유출 차단
 
[14.11.04] 바이두 클라우드
[14.11.04] 바이두 클라우드[14.11.04] 바이두 클라우드
[14.11.04] 바이두 클라우드
 
[14.10.24] 송죽 학사 for iOS
[14.10.24] 송죽 학사 for iOS[14.10.24] 송죽 학사 for iOS
[14.10.24] 송죽 학사 for iOS
 

[17.07.18] SCPC 1회 본선 - 트리