/*蓝桥——走多远(拓扑排序与动态规划的结合)
思路:先通过题目给定的顶点与顶点间的关系建立邻接表,再运用bfs进行拓扑序列的逐步删边的过程
其中具体表现就是队列的出队入队,最后得到拓扑排序,再用线性dp来解答,找到dp中的最大值即可*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define maxn 1000001 //顶点数
#define maxm 1000001 //边数
#define etype int //边的数据类型
typedef struct{ //邻接表中的节点的结构体定义,v代表数值,next代表该节点指向下一个节点的指针
int v;
int next;
}EDGE;
int head[maxn], ecount = 0; //head表示所有顶点对应关系的头部
EDGE edges[maxm];
void initedge(int n)
{
int i;
for (i = 0; i < n; i++)
{
head[i] = -1; //初始情况下没有对应关系
}
ecount = 0; //初始化
}
void addedge(int u, int v) //加边操作
{
edges[ecount].v = v;
edges[ecount].next = head[u];
head[u] = ecount;
ecount++;
}
int deg[maxn]; //表示
int quene[maxn], front, rear; //队列
int topsort(int n, int *ans) //拓扑操作,ans数组表示操作后得到的拓扑序列
{
int i;
int anssize = 0;
front = rear = 0;
memset(deg, 0, sizeof(deg));
for (i = 0; i < n; i++)
{
int u = i;
for (int e = head[u]; e != -1; e = edges[e].next) //遍历所有顶点,找出点的入度数量
{
int v = edges[e].v;
deg[v]++;
}
}
for (i = 0; i < n; i++) //找出入度为0的点并入队
{
if (!deg[i])
{
quene[rear++] = i;
}
}
while (front < rear) //拓扑操作的过程,deg为0表示该店入度为0, 即可入队
{
int u = quene[front++];
ans[anssize++] = u;
for (int e = head[u]; e != -1; e = edges[e].next)
{
int v = edges[e].v;
deg[v]--;
if (!deg[v])
{
quene[rear++] = v;
}
}
}
return anssize == n;
}
int ans[maxn];
int dp[maxn];
int main(int argc, char *argv[])
{
int n, m;
scanf("%d %d", &n, &m);
initedge(n);
while (m--)
{
int u, v;
scanf("%d %d", &u, &v);
u--;
v--;
addedge(u, v);
}
topsort(n, ans);
memset(dp, 0, sizeof(dp));
int ret = 0;
for (int i = n - 1; i >= 0; i--) //ans末尾的dp值一定为0,因为他没有出度
{
int u = ans[i];
for (int e = head[u]; e != -1; e = edges[e].next)
{
int v = edges[e].v;
dp[u] = fmax(dp[u], dp[v] + 1);
}
ret = fmax(ret, dp[u]);
}
printf("%d\n", ret);
return 0;
}
拓扑排序(dp与拓扑)
最新推荐文章于 2024-07-15 22:10:26 发布