zoukankan      html  css  js  c++  java
  • [USACO15JAN]草鉴定Grass Cownoisseur

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

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

    • (forall u,v in E)(exists u o v and v o u)

    (ecause)贝茜每次经过一个草场时只会吃一次草,( herefore)可以进行缩点,缩点后得到一个(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;
    }
    
  • 相关阅读:
    Castle Core 4.0.0 alpha001发布
    URL安全的Base64编码
    .NET Core RC2/RTM 明确了时间表
    一个免费的、跨平台的、开源音频编辑器Audacity
    Azure Service Fabric 开发环境搭建
    Microsoft Loves Linux
    微软将向Linux用户提供SQL Server程序
    微软收购Xamarin,你怎么看?
    我的梦幻2015,祝大家猴年吉祥,万事如意,幸福安康
    通用的序列号生成器库
  • 原文地址:https://www.cnblogs.com/lajioj/p/9742830.html
Copyright © 2011-2022 走看看