题意:
n个人,m个年龄比较,si,ti代表si年龄小于ti。被直接比较过年龄或者间接比较过的不能分在一组,问最少需要分在几组中。
解题思路:
一开始想的是去找一条最长的路,也即树的直径,这里是单向边的话直接找一遍就行。但是会有成环的情况,成环的点是都不能分在同一个组的,所以直接找最长路的话不一定能全部取出成环的点,所以缩点,然后再去找点值最大的一条路径,点值即一个强连通分量中点的个数。最后得到的点值就是答案了。
代码:
#include <stdio.h>
#include <iostream>
#include <vector>
#include <stack>
#define ps push_back
using namespace std;
const int maxn=1e5+5;
int DFS[maxn];
int low[maxn];
int belong[maxn];
int head[maxn];
int du[maxn];
bool instack[maxn];
vector<int>block[maxn];
vector<int>EDG[maxn];
struct node
{
int from;
int to;
int nex;
}edg[maxn*10];
int cnt;
void add(int u, int v)
{
edg[cnt].from=u;
edg[cnt].to=v;
edg[cnt].nex=head[u];
head[u]=cnt++;
}
int index, top, taj;
stack<int>sta;
void tarjin(int x, int fa)
{
int i;
low[x]=DFS[x]=index++;
sta.push(x);
instack[x]=true;
for(i=head[x]; i!=-1; i=edg[i].nex)
{
int to=edg[i].to;
// printf("%dto%d\n", x, to);
{
if(DFS[to]==-1)
{
tarjin(to, x);
low[x]=min(low[x], low[to]);
}
else if(instack[to])low[x]=min(low[x], DFS[to]);
}
}
if(DFS[x]==low[x])
{
block[taj].clear();
while(sta.top()!=x)
{
// printf("%d %d %d\n", taj, sta.top(), x);
instack[sta.top()]=false;
belong[sta.top()]=taj;
block[taj].ps(sta.top());
sta.pop();
}
// printf("%d %d %d\n", taj, sta.top(), x);
instack[sta.top()]=false;
belong[sta.top()]=taj;
block[taj].ps(sta.top());
sta.pop();
taj++;
}
return;
}
void tarjininit(int n)
{
index=top=taj=0;
for(int i=0; i<=n; i++)
{
instack[i]=false;
DFS[i]=low[i]=-1;
du[i]=0;
}
for(int i=1; i<=n; i++)
{
if(DFS[i]==-1)tarjin(i, 0);
}
return;
}
int ans;
int dp[maxn];
int dfs(int x)
{
if(dp[x]!=-1)return dp[x];
dp[x]=0;
int ma=0;
for(int i=0; i<(int)EDG[x].size(); i++)
{
int v=EDG[x][i];
ma=max(ma, dfs(v));
}
return dp[x]=ma+(int)block[x].size();
}
int main()
{
int x, y, i, j, n, m;
while(~scanf("%d%d", &n, &m))
{
ans=cnt=0;
for(i=0; i<=n; i++)head[i]=-1, belong[i]=-1, dp[i]=-1;
for(i=0; i<m; i++)
{
scanf("%d%d", &x, &y);
add(x, y);
}
tarjininit(n);
for(i=0; i<m; i++)
{
int u=belong[edg[i].from], v=belong[edg[i].to];
// printf("%d %d\n", edg[i].from, edg[i].to);
while(u<0);
while(v<0);
if(u!=v)
{
// printf("%d %d\n", u, v);
EDG[u].ps(v);
du[v]++;
}
}
ans=0;
for(i=0; i<taj; i++)
{
if(du[i]==0)
{
// printf("%d\n", i);
ans=max(ans, dfs(i));
}
}
printf("%d\n", ans);
for(i=0; i<taj; i++)EDG[i].clear();
}
}