zuccoj1450
来源:互联网 发布:新手淘宝卖家qq交流群 编辑:程序博客网 时间:2024/05/19 11:36
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(拓扑排序)
拓扑排序方法如下:
(1)从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它.
(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 100005int 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****************************************************************/