zoukankan      html  css  js  c++  java
  • 洛谷P3119 [USACO15JAN]Grass Cownoisseur G (tarjan缩点+边反向搭建处理)

    题目链接:https://www.luogu.com.cn/problem/P3119

    题目大意:给你m组单向边关系,你可以选择返回走一次,但是要保证出发点是1和终点是1,问你最大能到达几个点

    题目解法:

      首先我们可以通过缩点将一个强连通分量里的所有点变成一个点,并且可以知道缩点以后的图是没有环的,
      此时我们记缩点以后以一号点在第start个强连通分量里;
      然后用spaf得出以start到其他点(缩点以后的点)的最长路dis1[],然后用反向的路在得到所有点到start
      的最长路dis2[],最后我们可以遍历所以路的反向路得到答案;
      ans=max(ans,dis1[b]+dis2[a]-sum[start]);
    一些细节:

      SPFA建边的时候,可以少一步w,这个时候把siz[v]可以看做成w。还有就是建边思想,正向建边+反向建边的配合

    AC代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define eps 0.000000001
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=5e5+5;
    int tot,head[maxn];
    struct E{
        int to,next;
    }edge[maxn<<1];
    void add(int u,int v){
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    int tot1,head1[maxn];
    struct E1{
        int to,next,w;
    }edge1[maxn<<1];
    void add1(int u,int v){
        edge1[tot1].to=v;
        edge1[tot1].next=head1[u];
        head1[u]=tot1++;
    }
    int tot2,head2[maxn];
    struct E2{
        int to,next,w;
    }edge2[maxn<<1];
    void add2(int u,int v){
        edge2[tot2].to=v;
        edge2[tot2].next=head2[u];
        head2[u]=tot2++;
    }
    int n,m,uu[maxn],vv[maxn];
    int dfn[maxn],low[maxn],id[maxn],vis[maxn],cnt,tott;
    stack<int> s;int siz[maxn];
    void tarjan(int x){
        dfn[x]=low[x]=++tott;
        s.push(x);vis[x]=1;
        for(int i=head[x];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(!dfn[v]){
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }
            else if(vis[v]){
                low[x]=min(low[x],dfn[v]);
            }
        }
        if(low[x]==dfn[x]){
            ++cnt;
            while(1){
                int now=s.top();s.pop();
                id[now]=cnt;
                vis[now]=0;
                siz[cnt]+=1;
                if(x==now) break;
            }
        }
    }
    int d1[maxn],inq1[maxn];
    void SPFA1(int x){
        queue<int> q1;
        d1[x]=siz[x];q1.push(x);inq1[x]=1;
        while(!q1.empty()){
            int now=q1.front();q1.pop();
            inq1[now]=0;
            for(int i=head1[now];i!=-1;i=edge1[i].next){
                int v=edge1[i].to;
                if(d1[v]<d1[now]+siz[v]){
                    d1[v]=d1[now]+siz[v];
                    if(!inq1[v]){
                        inq1[v]=1;q1.push(v);
                    }
                }
            }
        }
    }
    int d2[maxn],inq2[maxn];
    void SPFA2(int x){
        queue<int> q2;
        d2[x]=siz[x];q2.push(x);inq2[x]=1;
        while(!q2.empty()){
            int now=q2.front();q2.pop();
            inq2[now]=0;
            for(int i=head2[now];i!=-1;i=edge2[i].next){
                int v=edge2[i].to;
                if(d2[v]<d2[now]+siz[v]){
                    d2[v]=d2[now]+siz[v];
                    if(!inq2[v]){
                        inq2[v]=1;q2.push(v);
                    }
                }
            }
        }
    }
    int main(){
        mem(head,-1);mem(head1,-1);mem(head2,-1);
        cin>>n>>m;tott=cnt=0;
        rep(i,1,m){
            cin>>uu[i]>>vv[i];
            add(uu[i],vv[i]);
        }
        rep(i,1,n){
            if(!dfn[i]) tarjan(i);
        }
        rep(i,1,m){
            if(id[uu[i]]==id[vv[i]]) continue;
            add1(id[uu[i]],id[vv[i]]);
            add2(id[vv[i]],id[uu[i]]);
        }
        SPFA1(id[1]);SPFA2(id[1]);
        int ans=siz[id[1]];
        rep(i,1,cnt){
            if(!d1[i]) continue;
            for(int j=head2[i];j!=-1;j=edge2[j].next){
                int v=edge2[j].to;
                if(!d2[v]) continue;
                ans=max(ans,d1[i]+d2[v]-siz[id[1]]);
            }
        }
        cout<<ans<<endl;
    }
    View Code
  • 相关阅读:
    对接某款商城系统[5]商城商品多级价格处理
    利用DelegatingHandler实现Web Api 的Api key校验
    采用Lambda表达式快速实现实体模型对象转换到DTO
    驱蚊器翁
    批量测试网络关系的小脚本
    jboss7访问日志功能及使用goaccess工具分析
    jetty使用jndi数据源
    sping junit test
    Too many open files解决方案及原理
    jboss7的JAX-WS客户端
  • 原文地址:https://www.cnblogs.com/Anonytt/p/13330912.html
Copyright © 2011-2022 走看看