Description
给你一张有向图,求出图中最长链的长度。如果图中存在环,那么我们认为链的长度是无限的。
链的定义是这样:如果A点能走到B点。那么所有从A点出发走到B点的路径都被认为是以A为始端,B为终端的链。链的长度为路径上顶点的数目(包括端点)。
Input
多组测试数据。
第一行输入n,m表示图的顶点数量与边的数量。(1<=n<=100000,0<=m<=100000)
接下来m行,每行输入x,y。表示x到y有一条有向边(1<=x,y<=n, x!=y)。
Output
输出所求答案。无限长输出INF
Sample Input
5 4
1 2
2 3
2 4
4 5
2 2
1 2
2 1
1 2
2 3
2 4
4 5
2 2
1 2
2 1
Sample Output
4
INF
INF
HINT
Source
Guo Zehui
分析:
这题主要是判断是否成环,不成环的情况就直接输出最长路即可
而判断是否成环这里要用到topsort(拓扑排序)
拓扑排序方法如下:
(2)从网中删去该顶点,并且删去从该顶点发出的全部有向边.
(3)重复上述两步,直到剩余的网中不再存在没有前趋的顶点为止.
可以每一次删除后让步数加1,然后把步数和顶点个数是否相等来判断是否成环
在dp[u]=max(dp[u],dp[x]+1)这里,因为可能有多个点连向u。
code:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
using namespace std;
queue <int> mm;
#define maxn 100005
int Max(int x,int y)
{
if(x>y)
return x;
return y;
}
int outdu[maxn],p[maxn],eid,step,n,dp[maxn];
struct s
{
int to,next;
}a[maxn*2];
void init()
{
int i;
memset(outdu,0,sizeof(outdu));
memset(p,-1,sizeof(p));
step=0;
eid=0;
for(i=1;i<=n;i++)
dp[i]=1;
while(!mm.empty())
mm.pop();
}
void ljb(int from,int to)
{
a[eid].to=to;
a[eid].next=p[from];
p[from]=eid++;
}
void bfs()
{
int v,u,x,i;
while(!mm.empty())
{
x=mm.front();
mm.pop();
for(v=p[x];v!=-1;v=a[v].next)
{
u=a[v].to;
outdu[u]--;
if(outdu[u]==0){
step++;
outdu[u]--;
mm.push(u);
}
dp[u]=Max(dp[u],dp[x]+1);
}
}
}
int main()
{
int m,x,y,i,ma;
while(~scanf("%d%d",&n,&m))
{
init();
while(m--){
scanf("%d%d",&x,&y);
outdu[y]++;
ljb(x,y);
}
for(i=1;i<=n;i++){
if(outdu[i]==0){
step++;
outdu[i]--;
mm.push(i);
}
}
bfs();
if(step!=n)
printf("INF\n");
else{
ma=dp[1];
for(i=2;i<=n;i++)
if(dp[i]>ma)
ma=dp[i];
printf("%d\n",ma);
}
}
return 0;
}
/**************************************************************
Problem: 1450
User: 31201128
Language: C++
Result: Accepted
Time:280 ms
Memory:3736 kb
****************************************************************/