问题描述
约翰有n块草场,编号1到n,这些草场由若干条单行道相连。奶牛贝西是美味牧草的鉴赏家,她想到达尽可能多的草场去品尝牧草。
贝西总是从1号草场出发,最后回到1号草场。她想经过尽可能多的草场,贝西在通一个草场只吃一次草,所以一个草场可以经过多次。因为草场是单行道连接,这给贝西的品鉴工作带来了很大的不便,贝西想偷偷逆向行走一次,但最多只能有一次逆行。问,贝西最多能吃到多少个草场的牧草。
输入格式
第一行,两个整数N和M(1<=N,M<=100000)
接下来M行,表示有M条单向道路,每条道路有连个整数X和Y表示,从X出发到达Y。
输出格式
一个整数,表示所求答案
样例输入
7 10
1 2
3 1
2 5
2 4
3 7
3 5
3 6
6 5
7 2
4 7
样例输出
6
提示
贝西的行走线路是1, 2, 4, 7, 2, 5, 3, 1 ,在5到3的时候逆行了一次。
题解
tarjan缩点然后用spfa跑分层图最长路或是用top排序dp求最长链
代码
#include<stdio.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
using namespace std;
#define maxn1 100005
#define pr cout<<
struct node{
int x,k;
};
int Last[maxn1],Next[maxn1],End[maxn1],St[maxn1];
int Last1[maxn1],Next1[maxn1],End1[maxn1],Len[maxn1];
int Last2[maxn1],Next2[maxn1],End2[maxn1],Len2[maxn1];
int cnt,scc,vis;
int dfn[maxn1],low[maxn1];
int be[maxn1],p[maxn1];
int n,m;
bool mark[maxn1][2],instack[maxn1];
stack<int>s;
queue<node>q;
int dis[maxn1][2];
void spfa()
{
int i,j;
node t;
t.x=be[1];t.k=0;
q.push(t);
mark[t.x][t.k]=true;
while(q.size())
{
node tmp=q.front();
q.pop();
mark[tmp.x][tmp.k]=false;
int st=tmp.x;
int k1=tmp.k;
for(i=Last1[st];i;i=Next1[i])
{
int en=End1[i];
// pr st<<"->"<<en<<" ";
if(dis[en][k1]<dis[st][k1]+Len[i])
{
dis[en][k1]=dis[st][k1]+Len[i];
if(mark[en][k1]==false){
node tt;
tt.x=en;
tt.k=k1;
q.push(tt);
mark[en][k1]=true;
}
}
}
if(k1==0)
{
for(i=Last2[st];i;i=Next2[i])
{
int en=End2[i];
if(dis[en][1]<dis[st][0]+Len2[i])
{
dis[en][1]=dis[st][0]+Len2[i];
if(mark[en][1]==false){
node tt;
tt.x=en;tt.k=1;
q.push(tt);
mark[en][1]=true;
}
}
}
}
}
}
void tj(int x)
{
int i;
dfn[x]=low[x]=++vis;
s.push(x);instack[x]=true;
for(i=Last[x];i;i=Next[i])
{
int en=End[i];
if(dfn[en]==false)
{
tj(en);
low[x]=min(low[x],low[en]);
}
else if(instack[en])
{
low[x]=min(low[x],dfn[en]);
}
}
if(dfn[x]==low[x]){
scc++;
int t;
do{
t=s.top();
s.pop();instack[t]=false;
be[t]=scc;
p[scc]++;
}while(t!=x);
}
}
void insert(int x,int y)
{
cnt++;
St[cnt]=x;
Next[cnt]=Last[x];
Last[x]=cnt;
End[cnt]=y;
}
void insert1(int x,int y,int z,int z1)
{
cnt++;
Next1[cnt]=Last1[x];
Last1[x]=cnt;
End1[cnt]=y;
Len[cnt]=z;
Next2[cnt]=Last2[y];
Last2[y]=cnt;
End2[cnt]=x;
Len2[cnt]=z1;
}
int main()
{
int i,j;
// freopen("taste.in","r",stdin);
// freopen("taste.out","w",stdout);
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
insert(x,y);
}
cnt=0;
for(i=1;i<=n;i++) if(dfn[i]==0) tj(i);
// for(i=1;i<=scc;i++) pr p[i];
for(i=1;i<=m;i++){
int x=St[i],y=End[i];
if(be[x]!=be[y])
{
insert1(be[x],be[y],p[be[y]],p[be[x]]);
}
}
// for(i=1;i<=n;i++) pr be[i];
spfa();
cout<<max(p[be[1]],max(dis[be[1]][1],dis[be[1]][0]));
}