강력 한 연결 분량 - tarjan 알고리즘 이 그림 에서 의 응용 (1)
그림 이 없 는 절 점 을 구 하 는 것 과 마찬가지 로 우 리 는 dfs 와 low 두 개의 배열 을 사용 해 야 한다. 그 의 미 는 여기 서 더 이상 군말 하지 않 는 다.그 밖 에 우 리 는 보조 창고 로 배열 을 하나 더 열 어야 한다.
강 한 연결 을 구 하 는 사고 와 절단 점 도 비슷 하 다.우 리 는 그림 에 대해 dfs, dfs 배열 과 low 배열 의 구법 을 구 할 때 와 마찬가지 로 dfs 가 한 점 에 도착 할 때마다 이 를 이미 달 한 것 으로 표시 하고 스 택 에 넣 습 니 다.점 x 의 모든 아웃 사 이 드 를 옮 겨 다 닌 후에 dfs [x] = low [x] 가 있 으 면 x 와 스 택 에 있 는 모든 것 이 x 이상 의 점 에서 강 한 연결 분량 을 구성 하고 스 택 에서 나 온 다 는 것 을 설명 합 니 다.필요 하 다 면 염색 등 을 할 수 있다.증명 은 다음 과 같다. 만약 에 x 의 서브 트 리 에 x 를 포함 하지 않 는 강 한 연결 분량 이 포함 되 어 있다 면 x 를 뿌리 로 하 는 dfs 가 끝나 기 전에 이 강 한 연결 분량 은 반드시 팝 업 될 것 이다.
이렇게 해서 우 리 는 그림 에 강 한 연결 분량 을 구 해 냈 다.
인기 있 는 소 P2341
이 문제 에서 한 무리의 소 가 하나의 강 한 연결 분량 을 구성한다 면 그 중의 한 마리 가 스타 젖소 라면 이 젖소 가 있 는 강 한 연결 분량 중의 모든 젖 소 는 스타 젖소 이다.또 어떤 강 한 연결 분량 이 나 오 면 이 강 한 연결 분량 의 모든 젖소 가 스타 젖소 가 아니다.그리고 두 개 이상 의 강 한 연결 분량 의 출 도가 0 이면 스타 젖소 가 존재 하지 않 는 다.
강 한 연결 분량 의 출 도와 입 도 에 대해 우 리 는 특정한 강 한 연결 분량 을 스 택 에서 꺼 낼 때 이 를 염색 하여 모든 강 한 연결 분량 을 구 한 후에 우 리 는 모든 변 을 옮 겨 다 닐 수 있다. 만약 에 변 의 양쪽 색 이 일치 하지 않 으 면 출발점 이 있 는 강 한 연결 분량 의 출 도 + 를 주 고 마지막 에 이미 세 어 진 출입 도 를 옮 겨 다 니 며 판단 하면 된다.
AC 코드:
#include
#include
using namespace std;
int n,m,head[10005],ecnt=1,x,y,cnt=1,ans;
int dfn[10005],low[10005],v[10005];
int s[10005],dfsc,h,c[10005],out[10005],size[10005];
//v:vis s:stack dfsc:dfs h:
//c:color out: cnt: size:
struct list{
int r,n;
}l[50005];
void add(int a,int b)
{
l[ecnt].r=b;
l[ecnt].n=head[a];
head[a]=ecnt++;
}
void pop(int x)
{
int num=1;
while(s[h-1]!=x)
{
num++;
v[s[h-1]]=0;
c[s[h-1]]=cnt;
h--;
}
c[x]=cnt;
h--;
size[cnt++]=num;
}
void dfs(int x)
{
low[x]=dfn[x]=++dfsc;
s[h++]=x;
v[x]=1;
for(int i=head[x];i;i=l[i].n)
{
int p=l[i].r;
if(!dfn[p])
{
dfs(p);
low[x]=min(low[p],low[x]);
}
else low[x]=min(low[p],low[x]);
}
if(dfn[x]==low[x]) pop(x);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) {scanf("%d%d",&x,&y);add(x,y);}
for(int i=1;i<=n;i++)
{
if(!dfn[i]) dfs(i);
else if(!dfn[i]) {printf("0");return 0;}
}
for(int i=1;i<=n;i++)
{
for(int j=head[i];j;j=l[j].n)
{
int p=l[j].r;
if(c[p]!=c[i]) out[c[i]]++;
}
}
for(int i=1;i<cnt;i++)
{
if(ans&&out[i]==0) {printf("0");return 0;}
if(out[i]==0) ans=size[i];
}
printf("%d",ans);
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에 따라 라이센스가 부여됩니다.