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

    约翰有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<cstdio>
    #include<cstring>
    #include<queue>
    #include<stack>
    #include<algorithm>
    using namespace std;
    const int maxn=1e5+10;
    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<int> 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(1)
            {
                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<pair<int,int> >q;
    void dijkstra(int x)
    {
        memset(vis,0,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
    !",u);
        //    printf("%d
    ?",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
    ",dis1[v]);
                }
            }
        }
    }
    
    void dijkstra2(int x)
    {
        memset(vis,0,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=1;i<=m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        for(int i=1;i<=n;i++)
        {
            if(!dfn[i]) dfs(i);
        }
    
        //memset(pre,0,sizeof(pre));
        
        for(int i=1;i<=n;i++)
        {
            sum[belong[i]]++;
        }
        //for(int i=1;i<=qw;i++) printf("%d ",sum[i]);
        for(int i=1;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[1]];    
        dijkstra(belong[1]);
        dijkstra2(belong[1]);
        //for(int i =1;i<=n;i++) printf("%d ",dis1[i]);
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)    
        {
            if(vis[belong[i]]||!dis1[belong[i]]) continue;
            vis[belong[i]]=1;
            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[1]]);
            }
        }
        printf("%d",ans);
        return 0;
    }
    
    
    


  • 相关阅读:
    Windows JScript 在 游览器 中运行 调试 Shell 文件系统
    autohotkey 符号链接 软连接 symbolink
    软链接 硬链接 测试
    SolidWorks 修改 基准面 标准坐标系
    手机 路径 WebDAV 映射 驱动器
    Win10上手机路径
    explorer 命令行
    单位公司 网络 封锁 屏蔽 深信 AC
    cobbler自动化部署原理篇
    Docker四种网络模式
  • 原文地址:https://www.cnblogs.com/WHFF521/p/11545358.html
Copyright © 2011-2022 走看看