P3119 [USACO15JAN]草鉴定
阅读原文时间:2023年07月09日阅读:3

约翰有n块草场,编号1到n,这些草场由若干条单行道相连。奶牛贝西是美味牧草的鉴赏家,她想到达尽可能多的草场去品尝牧草。

贝西总是从1号草场出发,最后回到1号草场。她想经过尽可能多的草场,贝西在通一个草场只吃一次草,所以一个草场可以经过多次。

因为草场是单行道连接,这给贝西的品鉴工作带来了很大的不便,贝西想偷偷逆向行走一次,但最多只能有一次逆行。问,贝西最多能吃到多少个草场的牧草。

输入:

第一行:草场数n,道路数m。

以下m行,每行x和y表明有x到y的单向边,不会有重复的道路出现。

输出:

一个数,逆行一次最多可以走几个草场。

输入 #1

7 10
1 2
3 1
2 5
2 4
3 7
3 5
3 6
6 5
7 2
4 7

输出 #1

6
好久没有这么正式的将题面搬过来了;
显然需要tarjan求强连通分量;
但是我只会到这里,但是看题;
允许一条边反向,有点眼熟,啊,那个,就是那个
我们先缩点,dijkstra正向求最长路,再反向求最长路
枚举反向的边;
dis1[x]+dis2[v]-sum[belong[1]];
但是我们要保证能回去

#include
#include
#include
#include
#include
using namespace std;
const int maxn=1e5+;
int n,m,pre[maxn],last[maxn],other[maxn],l;
int pre0[maxn],last0[maxn],other0[maxn],l0;
void add0(int x,int y)
{
l0++;
pre0[l0]=last0[x];
last0[x]=l0;
other0[l0]=y;
}
int dfn[maxn],low[maxn],cnt;
void add(int x,int y)
{
l++;
pre[l]=last[x];
last[x]=l;
other[l]=y;
}
int pre2[maxn],last2[maxn],other2[maxn],l2;
void add2(int x,int y)
{
l2++;
pre2[l2]=last2[x];
last2[x]=l2;
other2[l2]=y;
}

stack s;
int belong[maxn],qw;

void dfs(int x)
{
dfn[x]=low[x]=++cnt;
s.push(x);
for(int p=last[x];p;p=pre[p])
{
int v=other[p];
if(!dfn[v])
{
dfs(v);
low[x]=min(low[x],low[v]);
}
else if(!belong[v])
{
low[x]=min(low[x],dfn[v]);
}
}
if(dfn[x]==low[x])
{
belong[x]=++qw;
//printf("%d ",qw);
while()
{
int y=s.top();
s.pop();
belong[y]=qw;
if(x==y) break;
}
}
}

int sum[maxn];
int ans;
int vis[maxn];
int dis1[maxn],dis2[maxn];
priority_queue >q;
void dijkstra(int x)
{
memset(vis,,sizeof(vis));
dis1[x]=sum[x];
q.push(make_pair(dis1[x],x));
while(!q.empty())
{
int u=q.top().second;
q.pop();
// printf("%d\n!",u);
// printf("%d\n?",last[u]);
// if(vis[u]) continue;
// vis[u]=1;
for(int p=last0[u];p;p=pre0[p])
{
int v=other0[p];
//printf("!!");
if(dis1[v]<dis1[u]+sum[v])
{
dis1[v]=dis1[u]+sum[v];
q.push(make_pair(dis1[v],v));
//printf("%d\n",dis1[v]);
}
}
}
}

void dijkstra2(int x)
{
memset(vis,,sizeof(vis));
dis2[x]=sum[x];
q.push(make_pair(dis2[x],x));
while(!q.empty())
{
int u=q.top().second;
q.pop();
// if(vis[u]) continue;
// vis[u]=1;
for(int p=last2[u];p;p=pre2[p])
{
int v=other2[p];
if(dis2[v]<dis2[u]+sum[v])
{
dis2[v]=dis2[u]+sum[v];
q.push(make_pair(dis2[v],v));
}
}
}
}

int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i=;i<=n;i++)
{
if(!dfn[i]) dfs(i);
}

//memset(pre,0,sizeof(pre));

for(int i=;i<=n;i++)  
{  
    sum\[belong\[i\]\]++;  
}  
//for(int i=1;i<=qw;i++) printf("%d ",sum\[i\]);  
for(int i=;i<=n;i++)  
{  
    for(int p=last\[i\];p;p=pre\[p\])  
    {  
        int v=other\[p\];  
        if(belong\[i\]!=belong\[v\])  
        {  
            add0(belong\[i\],belong\[v\]);  
            add2(belong\[v\],belong\[i\]);  
        }  
    }  
}  
ans=sum\[belong\[\]\];  
dijkstra(belong\[\]);  
dijkstra2(belong\[\]);  
//for(int i =1;i<=n;i++) printf("%d ",dis1\[i\]);  
memset(vis,,sizeof(vis));  
for(int i=;i<=n;i++)  
{  
    if(vis\[belong\[i\]\]||!dis1\[belong\[i\]\]) continue;  
    vis\[belong\[i\]\]=;  
    int x=belong\[i\];  
    for(int p=last2\[x\];p;p=pre2\[p\])  
    {  
        int v=other2\[p\];  
        if(!dis2\[v\]) continue;  
        ans=max(ans,dis1\[x\]+dis2\[v\]-sum\[belong\[\]\]);  
    }  
}  
printf("%d",ans);  
return ;  

}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章