Upload
kenny-park
View
81
Download
3
Embed Size (px)
Citation preview
SCPC 1회 본선 - 트리
박현민
2017-07-18 1
목차
문제
배경 지식
해법
코드
참고 문헌
2017-07-18 2
문제Chapter 1
2017-07-18 3
2017-07-18 4
문제
2017-07-18 5
문제 (Cont’d)
배경 지식Chapter 2
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
해법Chapter 3
2017-07-18 14
Matrix M
For i in 1 ~ n– For j in i + 1 ~ n
• // Should make Mj,i to 0• (Row j) := Mi,i × (Row j) – Mj,i × (Row i)• 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
최소병목신장트리
코드Chapter 4
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){
int i,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%9C
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