Luogu3119[USACO15JAN]Grass Cownoisseur——Tarjan+图论建模

【题目描述】
约翰有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

说明:只要走1,2,4,7,2,5,3,1即可。


这道题要求我们求最大的强连通分量,但是我们可以走一次反向边,这点是这道题目的难点。
我们可以采用两种思路来做,接下来我都会介绍。首先无论如何,我们都要先用Tarjan缩点,将整张图缩成一个DAG。

思路1:
我们Tarjan之后就成为了一个DAG,我们在建新图的边时同时也将反向边建出来。我们将所有的强连通分量分成两类,一类是可以从1所在的强连通分量直接走到的,另一类是从1所在的强连通分量走反向边可以走到的。如果我们能从一个1类点走到另一个2类点。那么显然是可以的,所以我们枚举所有的1类点,并且枚举他们能够走到的所有2类点。然后更新答案即可。这个算法比较的暴力。
#include<bits/stdc++.h>
#include<vector>
#define MAXN 200005
using namespace std;
int read(){
    char c;int x;while(c=getchar(),c<'0'||c>'9');x=c-'0';
    while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';return x;
}
int n,m,head[MAXN],nxt[MAXN],to[MAXN],cnt,dfn[MAXN],low[MAXN],sta[MAXN],vis[MAXN],top;
int ta,co,col[MAXN],rec,vi[MAXN],fl,can[MAXN],back[MAXN],q[MAXN],h,t,ans;
void add(int x,int y){
    to[cnt]=y;nxt[cnt]=head[x];head[x]=cnt;cnt++;
}
void tarjan(int x)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值