[USACO15JAN]草鉴定Grass Cownoisseur

【题目描述】:
[USACO15JAN]草鉴定Grass Cownoisseur

【思路】:
首先我们先思考贝茜不走那条反边,那么对于任意强连通分量\(E\)易知:

  • \(\forall u,v \in E\),\(\exists u \to v \ and \ v \to u\)

\(\because\)贝茜每次经过一个草场时只会吃一次草,\(\therefore\)可以进行缩点,缩点后得到一个\(DAG\),统计每一个强连通分量的\(size\)值,表示此强连通分量中有多少个点,然后在\(DAG\)上跑\(DP\)即可。

但是这道题贝茜玩蛇皮,她还可以逆行一次。

所以我们应该换一个思路,缩完点后,考虑到逆行的情况,我们可以把图正反都建一次,设1号点所在的强连通分量为\(E\),求出\(dis1[]\) 和 \(dis2[]\),分别表示以\(E\)为起点和以\(E\)为中点的最长路,然后枚举每一个\(i\),那么答案就是:

  • \(max \{ dis1[i] +dis2[v] - size[E]\}\)。

这就相当于走了那条反边。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;

int n,m;

const int MAXN = 100005;

struct edge{
    int u,v,nxt;
}e[MAXN];int head[MAXN];int cnt = 0;int dfn[MAXN];int low[MAXN];int id = 0;int s[MAXN];int tot = 0;int Bcnt = 0;
int x[MAXN];int y[MAXN];bool vis[MAXN];int size[MAXN];int b[MAXN];bool back[MAXN];int dis1[MAXN];int dis2[MAXN];int ans = -inf;

inline void add(int u,int v){
    e[++cnt].u = u;e[cnt].v = v;e[cnt].nxt = head[u];head[u] = cnt;
}

inline void tarjan(int u){
    low[u] = dfn[u] = ++id;
    s[++tot]=u;vis[u] = 1;
    for(int i=head[u];i;i=e[i].nxt){
        int v = e[i].v;
        if(!dfn[v]){
            tarjan(v);
            low[u] = min(low[u] , low[v]);
        }
        else if(vis[v]) low[u] = min(low[u] , dfn[v]);
    }

    if(dfn[u] == low[u]){
        int j=0;Bcnt++;
        while(j ^ u){
            j = s[tot--];
            vis[j] = 0;
            b[j] = Bcnt;
            size[Bcnt]++;
        }
    }
}

inline bool cmp(int a,int b){
    return a > b;
}

queue<int>q;
inline void dp(int *dis){
    memset(dis,0,sizeof dis);
    memset(vis,0,sizeof vis);
    dis[b[1]] = size[b[1]];
    q.push(b[1]);

    while(!q.empty()){
        int u = q.front();q.pop();vis[u] = 0;
        for(int i=head[u];i;i=e[i].nxt){
            int v = e[i].v;
            if(dis[v] < dis[u] + size[v]){
                dis[v] = dis[u] + size[v];
                if(!vis[v]){
                    q.push(v);
                    vis[v] = 1;
                }
            }
        }
    }
}

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

    memset(head,0,sizeof head);cnt = 0;
    for(int i=1;i<=m;++i){
        if(b[x[i]] ^ b[y[i]]){
            add(b[x[i]] , b[y[i]]);
        }
    }
    for(int i=head[b[1]];i;i=e[i].nxt){
        int v = e[i].v;
        back[v] = 1;
    }
    dp(dis1);

    memset(head,0,sizeof head);cnt = 0;
    memset(back,0,sizeof back);
    for(int i=1;i<=m;++i){
        if(b[x[i]] ^ b[y[i]]){
            add(b[y[i]] , b[x[i]]);
        }
    }
    for(int i=head[b[1]];i;i=e[i].nxt){
        int v = e[i].v;
        back[v] = 1;
    }
    dp(dis2);

    for(int i=1;i<=Bcnt;++i){
        if(!dis1[i]) continue;
        for(int j=head[i];j;j=e[j].nxt){
            int v = e[j].v;
            if(!dis2[v]) continue;
            ans = max(ans , (dis1[i] + dis2[v] - size[b[1]]));
        }
    }
    printf("%d",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/lajioj/p/9742830.html

时间: 2024-10-30 10:52:56

[USACO15JAN]草鉴定Grass Cownoisseur的相关文章

洛谷 P3119 [USACO15JAN]草鉴定Grass Cownoisseur

P3119 [USACO15JAN]草鉴定Grass Cownoisseur tarjan缩点,正反spfa,枚举边,更新最大值 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define maxn 1000000 4 #define inf 0x3f3f3f3f 5 int n,m,x[maxn],y[maxn],z,num,head[maxn],head2[maxn],tim,ans,tot,dis1[maxn],dis2[maxn

洛谷——P3119 [USACO15JAN]草鉴定Grass Cownoisseur

P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-way cow paths all over his farm. The farm consists of N fields, conveniently numbered 1..N, with each one-way co

P3119 [USACO15JAN]草鉴定Grass Cownoisseur

P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-way cow paths all over his farm. The farm consists of N fields, conveniently numbered 1..N, with each one-way co

[USACO15JAN]草鉴定Grass Cownoisseur(分层图+tarjan)

[USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-way cow paths all over his farm. The farm consists of N fields, conveniently numbered 1..N, with each one-way cow path

luogu P3119 [USACO15JAN]草鉴定Grass Cownoisseur

题目描述 In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-way cow paths all over his farm. The farm consists of N fields, conveniently numbered 1..N, with each one-way cow path connecting a pair of fields. For

Luogu 3119 [USACO15JAN]草鉴定Grass Cownoisseur

思路很乱,写个博客理一理. 缩点 + dp. 首先发现把一个环上的边反向是意义不大的,这样子不但不好算,而且相当于浪费了一次反向的机会.反正一个强连通分量里的点绕一遍都可以走到,所以我们缩点之后把一个强连通分量放在一起处理. 设$st$表示缩点之后$1$所在的点,设$f_{x}$表示从$st$走到$x$的最长链,$g_{x}$表示从$x$走到$st$的最长链,因为把一个$DAG$上的边反向一下并不会走重复的点,那么我们最后枚举一下边$(x, y)$,把它反向,这样子$f_{x} + g_{y}

BZOJ 3887[Usaco2015 Jan]Grass Cownoisseur

题面: 3887: [Usaco2015 Jan]Grass Cownoisseur Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 237  Solved: 130[Submit][Status][Discuss] Description In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-way cow pat

bzoj3887: [Usaco2015 Jan]Grass Cownoisseur

题意: 给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在路径中无论出现多少正整数次对答案的贡献均为1) =>有向图我们先考虑缩点.然后观察缩点后的图可以发现新的路径中必定只有一条边是反向的才符合条件.那么我们可以联想到某道最短路的题将边反向存一遍后分别从s和t跑一跑.那么这里bfs跑一跑就行了.然后有一个坑点:这种重建图的注意es和edges不然es会在中途就被修改掉了... #include<cstdio> #

【tarjan+拓扑】BZOJ3887-[Usaco2015 Jan]Grass Cownoisseur

[题目大意] 给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在路径中无论出现多少正整数次对答案的贡献均为1) [思路] 首先缩点,对于每一个联通块求出正图和反图中节点1所在的联通块到它的最长节点数.这个用拓扑排序处理一下. 枚举每一条边取反,对于边(u,v),其取反后的距离就等于dis[u所在的联通快]+dis[v所在的联通块]-dis[1所在的联通块](因为会被重复计算不要忘记减去) 我一开始非常脑抽地在想会不会发生这