hdu 1233 또는 원활 한 공정 최소 생 성 트 리 (prim 알고리즘 + kruskal 알고리즘)
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Problem Description
모 성에 서 마을 의 교통 상황 을 조사 하여 얻 은 통계표 에는 임의의 두 마을 간 의 거리 가 열거 되 어 있다.성 정부의 '원활 한 공사' 목 표 는 성 전체의 어느 두 마을 간 에 도 도로 교통 을 실현 할 수 있 도록 하 는 것 이다.가장 작은 도로 의 총 길 이 를 계산 해 주세요.
Input
테스트 입력 은 약간의 테스트 용례 를 포함한다.각 테스트 용례 의 첫 번 째 줄 은 마을 수 N (< 100) 을 드 립 니 다.이 어 N (N - 1) / 2 줄 은 마을 간 의 거리 에 대응 하고 각 줄 은 두 마을 의 번호 와 이 두 마을 간 의 거 리 를 나타 낸다.간단하게 말하자면, 마을 은 1 부터 N 까지 번 호 를 매 긴 다.
N 이 0 일 때 입력 이 끝나 면 이 용례 는 처리 되 지 않 습 니 다.
Output
각 테스트 사례 에 대해 서 는 1 줄 에서 가장 작은 도로 총 길 이 를 출력 한다.
Sample Input
3
1 2 1
1 3 2
2 3 4
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
0
Sample Output
3
5
Hint
Hint
Huge input, scanf is recommended.
무방 향 대역 권 연결 그림 G 에서 연결 서브 트 리 가 모든 정점 을 포함 하고 이 정점 을 연결 하 는 변 권 의 합 이 가장 작 으 면,
그럼 이 연결 서브 맵 은 G 의 최소 생 성 트 리 입 니 다.최소 생 성 트 리 를 구 하 는 흔 한 알고리즘 은 Prim 알고리즘 입 니 다.
prim 알고리즘 (시간 복잡 도 는 O (n ^ 3)):
Prim 알고리즘 의 기본 사상 은:
1) 두 개의 집합 V 와 S 를 설정 하고, 한 개의 정점 을 시작 점 으로 임의로 선택 하여, 시작 점 을 집합 S 에 넣 고, 나머지 정점 은 집합 에 저장한다.
V 중;2) 그리고 욕심 전략 을 사용 하여 길이 가 가장 짧 고 단점 을 각각 S 와 V 에서 선택 하 십시오 (즉, 최소 생 성 트 리 중 하나 입 니 다.
변) 이 변 이 V 에 있 는 단점 을 집합 S 에 넣는다.3) S 에 모든 정점 이 포 함 될 때 까지 2) 단 계 를 반복 한다.
#include<stdio.h>
#include<string.h>
#define inf 0x3f3f3f3f
int map[100][100],s[100],vis[100];
int n,m;
int prim()
{
int i,j,t,p,min,minpos,cnt;
int ans=0;
cnt=0; /* */
vis[1]=1; /* */
s[cnt++]=1; /*s */
while(cnt<n) /* */
{
t=cnt;
min=inf;
for(i=0;i<t;i++)
{
p=s[i];
for(j=1;j<=n;j++)
{
if(!vis[j]&&map[p][j]<min) /* ,*/
{
min=map[p][j];
minpos=j; /* */
}
}
}
ans+=min;
s[cnt++]=minpos; /* */
vis[minpos]=1;
}
return ans;
}
int main()
{
int u,v,w,i;
while(~scanf("%d",&n)&&n)
{
m=n*(n-1)/2;
memset(vis,0,sizeof(vis));
memset(map,inf,sizeof(map));
for(i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&w);
map[u][v]=w;
map[v][u]=w;
}
int sum=prim();
printf("%d
",sum);
}
return 0;
}
위의 알고리즘 은 세 가지 순환 이 있 습 니 다. 시간 복잡 도 는 O (N ^ 3) 입 니 다. 욕심 전략 을 사용 하기 때문에 집합 S 에 새로운 정점 을 추가 할 때마다 V 의 각 점 에서 S 의 점 까지 의 최소 변 의 길 이 를 바 꿀 수 있 습 니 다. 따라서 하나의 배열 nearest [N] (N 은 정점 개수) 를 사용 할 수 있 습 니 다.최소 수 를 생 성 하 는 과정 에서 V 의 각 점 에서 S 중점 까지 의 최소 변 길 이 를 기록 하고, 다른 배열 adj [N] 로 이 변 의 최소 대응 하 는 인접 점 을 기록 합 니 다. 그러면 O (N) 의 시간 은 가장 짧 은 변 을 찾 고, O (N) 의 시간 에 nearest [N] 과 adj [N] 을 업데이트 할 수 있 습 니 다. 따라서 O (N ^ 2) 의 알고리즘 을 얻 을 수 있 습 니 다.
#include<stdio.h>
#include<string.h>
#define inf 0x3f3f3f3f
int map[100][100];
int n,m;
/* S, V*/
int vis[100]; // S
int adj[100]; // S
int nearest[100]; // V S
int prim()
{
int i,j,min;
int ans=0;
vis[1]=1;
for(i=2;i<=n;i++)
{
nearest[i]=map[1][i];
adj[i]=1;
}
int cnt=n-1; /* */
while(cnt--)
{
min=inf;
j=1;
for(i=1;i<=n;i++)
{
if(!vis[i]&&nearest[i]<min)
{
min=nearest[i];
j=i;
}
}
ans+=map[j][adj[j]];
vis[j]=1;
for(i=1;i<=n;i++)
{
if(!vis[i]&&map[i][j]<nearest[i])
{
nearest[i]=map[i][j]; /* */
adj[i]=j; /* */
}
}
}
return ans;
}
int main()
{
int i,sum,u,v,w;
while(~scanf("%d",&n)&&n)
{
memset(vis,0,sizeof(vis));
memset(map,0,sizeof(map));
m=n*(n-1)/2;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&w);
map[u][v]=map[v][u]=w;
}
sum=prim();
printf("%d
",sum);
}
return 0 ;
}
Kruskal 알고리즘 (시간 복잡 도 O (ElogE), E 는 변수):
연결 되 지 않 은 그림 G = (V, E), V = {1, 2,..., n} 을 지정 합 니 다. Kruskal 알고리즘 구조 G 의 최소 생 성 트 리 의 기본 사상 은 다음 과 같 습 니 다.
(1) 우선 G 의 n 개 정점 을 n 개의 고립 된 연결 지점 으로 본다.
(2) 첫 번 째 변 부터 변 권 이 증가 하 는 순서에 따라 각 변 을 검사 합 니 다. 그리고 다음 방법 에 따라 두 개의 서로 다른 연결 지점 을 연결 합 니 다. k 조 변 (v, w) 을 볼 때 점 v 와 w 가 각각 현재 두 개의 서로 다른 연결 지점 T1 과 T2 의 점 이 라면 변 (v, w) 을 사용 합 니 다.T1 과 T2 를 하나의 연결 지점 으로 연결 한 다음 k + 1 개의 변 을 계속 봅 니 다. 점 v 와 w 가 현재 같은 연결 지점 에 있 으 면 k + 1 개의 변 을 직접 봅 니 다. 이 과정 은 하나의 연결 지점 만 남 았 을 때 까지 진 행 됩 니 다.
이때 G 를 구성 하 는 최소 생 성 트 리 입 니 다.
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int father[100];
int n,m;
struct point
{
int u;
int v;
int w;
}a[5000];
bool comp(point a1,point a2) /* */
{
return a1.w<a2.w;
}
void initial() /* */
{
for(int i=0;i<=100;i++)
father[i]=i;
}
int find(int x) /* */
{
if(father[x]==x)
return x;
return find(father[x]);
}
void merge(int p,int q) /* */
{
int pp=find(p);
int qq=find(q);
if(pp!=qq)
{
if(pp<qq)
father[qq]=pp;
else
father[pp]=qq;
}
}
int kruskal()
{
initial(); /* */
int ans=0;
sort(a+1,a+m+1,comp); /* */
for(int i=1;i<=m;i++)
{
int x=find(a[i].u);
int y=find(a[i].v);
if(x!=y) /* */
{
ans+=a[i].w;
merge(x,y); /* */
}
}
return ans;
}
int main()
{
int i,sum;
while(~scanf("%d",&n)&&n!=0)
{
m=n*(n-1)/2;
for(i=1;i<=m;i++)
scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
sum=kruskal();
printf("%d
",sum);
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【Codility Lesson3】FrogJmpA small frog wants to get to the other side of the road. The frog is currently located at position X and wants to get to...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.