zoukankan      html  css  js  c++  java
  • 洛谷P3436[POI2006]PRO-Professor Szu (Tarjan缩点+反向建边拓扑排序+自环处理+重边处理)

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

    题目大意:给你n个点(第n+1个点为最终点)和m条边,问你从1~n个点走到第n+1个点的不同路线的数量(这里规定路线中但凡有一条不一样,那么这就是不同路线)

    题目陷阱:我们需要考虑对于重边和自环的处理。

    题目解法:我们可以利用Tarjan强联通缩点,缩点完的每个连通块事实上可以看做成可以无限走(因为绕圈嘛),所以我们可以统计每个连通块的数量,如果该连通块数量>1的话就把它的值dp[i]看做LIM,当然我们需要考虑到自环也是可以绕圈走自己,所以当遇到自环情况时,siz[i]+=1,dp[i]=LIM。

    接下来的处理方法就是关于拓扑排序反向建边了,这里不同于以前我写题的习惯(喜欢用记忆化搜索),因为这里会有重边的情况出现,所以我们得用拓扑排序来处理。我们反向建边之后,实际上有一些indeg[i]==0的点他是无效的,因为此点i必定到达不了id[n+1],所以我们可以把id[n+1]的值(即dp[id[n+1]]设置为1,并且对该点打标记,即vis[id[i+1]]=true,以后但凡vis值等于1的都代表可以从终点n+1走到的,是有用点)。接下来就是基本拓扑排序操作了我就不多赘述了,可以看看我的代码。

    #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 LIM 36500
    #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=1e6+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 n,m;
    int low[maxn],dfn[maxn],vis[maxn],id[maxn],cnt,tott;
    stack<int> s;int siz[maxn];
    void tarjan(int x){
        low[x]=dfn[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();
                vis[now]=0;
                id[now]=cnt;
                siz[cnt]+=1;
                if(now==x) break;
            }
        }
    }
    int uu[maxn],vv[maxn],indeg[maxn];
    queue<int> q;int dp[maxn];
    void topsort(){
        mem(vis,0);
        dp[id[n+1]]=1;vis[id[n+1]]=1;
        rep(i,1,cnt) if(!indeg[i]){q.push(i);}
        while(!q.empty()){
            int now=q.front();q.pop();
            for(int i=head[now];i!=-1;i=edge[i].next){
                int v=edge[i].to;
                if(--indeg[v]==0){
                    q.push(v);
                }
                if(vis[now]) vis[v]=1;
                dp[v]+=dp[now];
                if(siz[v]>1&&vis[v]) dp[v]=LIM;            
                if(dp[v]>LIM) dp[v]=LIM;
            }
        }
    }
    int f[maxn];
    int main(){
        scanf("%d%d",&n,&m);mem(head,-1);
        tott=cnt=0;
        rep(i,1,m){
            scanf("%d%d",&vv[i],&uu[i]);
            add(uu[i],vv[i]);
        }
        rep(i,1,n+1){
            if(!dfn[i]) tarjan(i);
        }
        mem(head,-1);mem(vis,0);mem(edge,0);tot=0;
        rep(i,1,m){
            if(uu[i]==vv[i]) siz[id[uu[i]]]+=1;
        }
        rep(i,1,m){
            if(id[uu[i]]==id[vv[i]]) continue;
            add(id[uu[i]],id[vv[i]]);
            indeg[id[vv[i]]]+=1;
        }
        topsort();
        int ans=0,num=0;
        rep(i,1,n){
            if(vis[id[i]]){
                f[i]=dp[id[i]];
                ans=max(ans,f[i]);
            }
        }
        rep(i,1,n){
            if(vis[id[i]]){
                if(f[i]==ans) ++num;
            }
        }
        if(ans==LIM) puts("zawsze");
        else cout<<ans<<endl;
        cout<<num<<endl;
        rep(i,1,n){
            if(vis[id[i]]&&f[i]==ans){
                cout<<i<<" ";
            }
        }
    }
    View Code
  • 相关阅读:
    OPPO R9sPlus MIFlash线刷TWRP Recovery ROOT详细教程
    OPPO R11 R11plus系列 解锁BootLoader ROOT Xposed 你的手机你做主
    努比亚(nubia) M2青春版 NX573J 解锁BootLoader 并进入临时recovery ROOT
    华为 荣耀 等手机解锁BootLoader
    青橙 M4 解锁BootLoader 并刷入recovery ROOT
    程序员修炼之道阅读笔03
    冲刺8
    典型用户模板分析
    学习进度八
    冲刺7
  • 原文地址:https://www.cnblogs.com/Anonytt/p/13308129.html
Copyright © 2011-2022 走看看