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;
    }
    
    
    


  • 相关阅读:
    Docker
    Dotted lines by default in ViVA
    8245H(C2)光猫配置方法
    两种将verilog网表转为spice网表的方法
    calibredrv create reference cell
    怎么flatten一个GDS所有层次
    路由器后面访问光猫
    贝尔IPTV
    PDK导出的cdl MOS四端顺序不正确
    如何删除已经存在lib的techfile
  • 原文地址:https://www.cnblogs.com/WHFF521/p/11545358.html
Copyright © 2011-2022 走看看