nyoj-895 How many ways [그림에서 dp+ 토폴로지]
3456 단어 토폴로지 정렬
How many ways?
시간 제한:
1000ms | 메모리 제한:
65535 KB
난이도:
4
묘사
n개의 점 m변의 유방향 무환도를 주고 점 1부터 점 n까지 모두 몇 개의 경로가 있느냐고 묻는다.(결과 10007 모델링)
입력
다중 테스트 데이터.
첫 번째 줄의 두 개수, n과 m(2<=n<=100,2<=m<=10000).
출력
각 그룹의 테스트 데이터 출력은 점 1에서 점 n까지의 방안 수가 10007에서 모형을 추출한 후의 값을 나타낸다.
우선, 내가 이 문제를 분석한 것은 그림의 dp이다.
dp[i][j]로 i점->j점의 최대 경로를 표시합니다
dp[0][j]에서 j점 전체의 최대 경로 수를 기록합니다
g[i][j]는 i점에서 j점까지의 변수
상태 전환 방정식은 다음과 같습니다.
dp[u][v]=Max(dp[0][u]*g[u][v]);
dp[0][v]=∑(Max(dp[u][v]));u는 v에 연결할 수 있는 모든 점입니다
전체적인 의미는 한 점의 최대 경로수는sumv=∑(sumu*count e)이다.v의 최대 경로 수 = 모든 (v의 최대 경로 수 * v에서 u의 변수) 의 합
다음은 모든 변을 열거하고 dp값을 업데이트하는 것입니다.하나의 점의 dp값이 바뀌면 연결된 점과 그 이후의 dp값은 모두 변할 수 있다.그래서 더 이상 업데이트가 없을 때까지 모든 변이 dp값을 업데이트합니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Max_V 110
long long int dp[Max_V][Max_V];
long long int g[Max_V][Max_V];
int n,m;
void init()
{
memset(dp,0,sizeof(dp));
memset(g,0,sizeof(g));
}
int main()
{
int i;
while(~scanf("%d%d",&n,&m))
{
init();
int u,v;
for(i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
g[u][v]++;
}
dp[0][1]=1;// 1
bool flag=true;
while(flag)
{
flag=false;
//
for(u=1;u<=n;u++)
for(v=1;v<=n;v++)
{
if(dp[u][v]<g[u][v]*dp[0][u])
{
flag=true;
//dp[0][v] ,
// dp[u][v]
// dp[u][v]
dp[0][v]-=dp[u][v];
dp[u][v]=g[u][v]*dp[0][u];
dp[0][v]+=dp[u][v];
}
}
}
printf("%lld
",dp[0][n]%10007);
}
return 0;
}
하지만 문제가 생겼다.데이터 범위가 매우 넓어서 롱 롱 int를 훨씬 초과한다.모형을 구한 후에 크기를 비교하는 것은 무효이기 때문이다.그럼 이 문제를 어떻게 해결할까요?
키워드:유방향 루프 없음
Lenovo: DAG(토폴로지 정렬)
AOV 네트워크로 토폴로지 서열을 구성하는 토폴로지 정렬 알고리즘은 입도 0의 정점이 존재하지 않을 때까지 다음과 같은 두 단계를 반복한다.
반복 실행 (1) 입도 0의 정점을 선택한다.(2) 네트에서 이 교점과 모든 아웃라인을 삭제합니다.
이렇게 하면 출입도가 0인 점을 끊임없이 열거한다.
상부의 사고방식을 이어받다.한 점의 입도가 0이라는 것은 이 점이 다시는 다른 점에 의해 업데이트되지 않을 것이라는 것을 설명하는 것입니까?이 점이 끝까지 업데이트되었다는 거 아니에요?
그러면 dp[0][u]는 더 이상 바뀌지 않을 것이다.dp[u][v]도 이에 따라 고정된다.이렇게 하면 문제는 단순한 추이식이 되고 dp[]수조는 2차원에서 1차원으로 최적화될 수 있다. dp[v]+=dp[u]*g[u][v];dp[u] 고정(u의 입도는 0이기 때문에 dp[u]는 다시 변경되지 않기 때문에 dp[u]는 현재 최대 경로수), g[u][v]는 고정됩니다.
더 이상 크기를 판단할 필요가 없다.추출 연산을 이용할 수 있다.
따라서 이 점에서 다른 점을 업데이트한 후에 이 점과 그 아웃라인을 삭제할 수 있고 출입도가 0인 점을 만들 수 있다.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define Max_V 110
#define mod 10007
int n,m;
int indeg[Max_V];
int g[Max_V][Max_V];
int dp[Max_V];
bool vis[Max_V];
void init()
{
memset(indeg,0,sizeof(indeg));
memset(g,0,sizeof(g));
memset(dp,0,sizeof(dp));
memset(vis,0,sizeof(vis));
}
int main()
{
int i;
while(~scanf("%d%d",&n,&m))
{
init();
int u,v;
for(i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
g[u][v]++;
indeg[v]++;
}
dp[1]=1;
while(true)
{
for(u=1;u<=n;u++)// 0
if(!indeg[u]&&!vis[u])
break;
if(u>=n)
break;
vis[u]=1;//
for(v=1;v<=n;v++)
if(g[u][v])
{
dp[v]+=dp[u]*g[u][v];//(a+b)%m=(a%m+b%m)%m
dp[v]%=mod;
indeg[v]-=g[u][v];//
}
}
printf("%d
",dp[n]);
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[APIO2009] 스윕 계획(강연통 컴포넌트+축소점+토폴로지 정렬+dp)제목: 지정된 시작점에서 시작하여 임의의 지정된 끝점까지 멈추는 지향도를 지정하여 지나간 모든 결점의 최대 점권과포인트, 모서리 수<=500000 하나의 강연통분량 내의 점은 서로 도달할 수 있기 때문에 그 중의 한...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.