zoukankan      html  css  js  c++  java
  • 洛谷P1262+Tarjan缩点

    本题是个有关Tarjan的题。
    首先我们来预习(温习)一下tarjan缩点:SCC是相互可达,先跑Tarjan然后建个新图。
    洛谷板子:P3387

    Code:

    #include<iostream>
    #include<cstdio>
    #include<stack>
    #include<queue>
    #include<cstring>
    #define INF 0x3f3f3f3f
    #define ll long long
    #define maxn 100001
    using namespace std;
    struct Edge{
        int nxt,to,dis;
    }edge[maxn];
    int n,m,low[maxn],dfn[maxn],a[maxn],tot[maxn],ans,num_edge,qaq[maxn],qwq[maxn],head[maxn],cnt,sccnum[maxn],vis[maxn],dis[maxn],scc_cnt;
    stack<int> s;
    inline void addedge(int from,int to){
        edge[++num_edge].nxt=head[from];
        edge[num_edge].to=to;
        head[from]=num_edge;
    }
    void tarjan(int x){
        dfn[x]=low[x]=++cnt;
        s.push(x);
        for(int i=head[x];i;i=edge[i].nxt){
            int y=edge[i].to;
            if(!dfn[y]){
                tarjan(y);
                low[x]=min(low[x],low[y]);
            }
            else if(!sccnum[y]){
                low[x]=min(dfn[y],low[x]);
            }
        }
        if(low[x]==dfn[x]){
            scc_cnt++;
            for(;;){
                //num[scc_cnt]++;
                int y=s.top();
                tot[scc_cnt]+=a[y];
                s.pop();
                sccnum[y]=scc_cnt;
                if(y==x) break;
            }
        }
    }
    inline void spfa(int s){
        queue<int> q;
        memset(dis,0,sizeof(dis));
        memset(vis,0,sizeof(vis));
        vis[s]=1;
        dis[s]=tot[s];
        q.push(s);
        while(!q.empty()){
            int x=q.front();
            q.pop();
            vis[x]=0;
            for(int i=head[x];i;i=edge[i].nxt){
                int y=edge[i].to;
                if(dis[y]<dis[x]+tot[y]){
                    dis[y]=dis[x]+tot[y];
                    if(vis[y]==0){
                        q.push(y);
                        vis[y]=1;
                    }
                }
            }
        }
        for(int i=1;i<=scc_cnt;i++){
            ans=max(ans,dis[i]);
        }
    }
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        for(int i=1;i<=m;i++){
            int x,y;
            cin>>x>>y;
            addedge(x,y);
            qwq[i]=x;
            qaq[i]=y;
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i]) tarjan(i);
        }
        memset(edge,0,sizeof(edge));
        memset(head,0,sizeof(head));
        num_edge=0;
        for(int i=1;i<=m;i++){
            if(sccnum[qwq[i]]!=sccnum[qaq[i]]){
                addedge(sccnum[qwq[i]],sccnum[qaq[i]]);
            }
        }
        for(int i=1;i<=scc_cnt;i++){
            spfa(i);
        }
        cout<<ans;
        return 0;
    }

    我们再考虑间谍网络这个题。
    统计一下入度,没了。
    Code:

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<stack>
    #include<cmath>
    #define ll long long
    #define maxn 100001
    #define INF 0x3f3f3f3f
    using namespace std;
    struct Edge{
        int nxt,to,dis;
    }edge[maxn];
    int n,m,low[maxn],dfn[maxn],rd[maxn],a[maxn],tot[maxn],ans,num_edge,qaq[maxn],qwq[maxn],head[maxn],cnt,sccnum[maxn],vis[maxn],dis[maxn],scc_cnt;
    stack<int> s;
    inline void addedge(int from,int to){
        edge[++num_edge].nxt=head[from];
        edge[num_edge].to=to;
        head[from]=num_edge;
    }
    void tarjan(int x){
        dfn[x]=low[x]=++cnt;
        s.push(x);
        for(int i=head[x];i;i=edge[i].nxt){
            int y=edge[i].to;
            if(!dfn[y]){
                tarjan(y);
                low[x]=min(low[x],low[y]);
            }
            else if(!sccnum[y]){
                low[x]=min(dfn[y],low[x]);
            }
        }
        if(low[x]==dfn[x]){
            scc_cnt++;
            for(;;){
                //num[scc_cnt]++;
                int y=s.top();
               // tot[scc_cnt]+=a[y];
                tot[scc_cnt]=min(tot[scc_cnt],a[y]);
                s.pop();
                sccnum[y]=scc_cnt;
                if(y==x) break;
            }
        }
    }
    int main(){
        memset(a,INF,sizeof(a));
        memset(tot,INF,sizeof(tot));
        int p,r;
        cin>>n>>p;
        for(int i=1;i<=p;i++){
           // int x,y;
            //cin>>x>>y;
            //addedge(x,y);
            //qwq[i]=x;
            //qaq[i]=y;
            int x,y;
            cin>>x>>y;
            a[x]=y;
        }
        cin>>r;
        for(int i=1;i<=r;i++){
            int x,y;
            cin>>x>>y;
            addedge(x,y);
        //    qwq[i]=x;
        //    qaq[i]=y;
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i]&&a[i]!=INF) tarjan(i);
        }
      //  memset(edge,0,sizeof(edge));
      //  memset(head,0,sizeof(head));
       // num_edge=0;
        for(int i=1;i<=n;i++){
            if(!dfn[i]){
                cout<<"NO"<<endl;
                cout<<i<<endl;
                return 0;
            }
        }
        for(int i=1;i<=n;i++)
            for(int j=head[i];j;j=edge[j].nxt){
                if(sccnum[i]!=sccnum[edge[j].to]){
                rd[sccnum[edge[j].to]]++; 
            }
        }
       for(int i=1;i<=scc_cnt;i++){
           if(!rd[i]){
               ans+=tot[i];
           }
       }
       cout<<"YES"<<endl;
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    js使用html2canvas实现页面截图并保存图片
    微信小程序之图片base64解码
    微信小程序之回调函数
    小程序横向滚动
    搭建vue开发环境的步骤
    检测算法简介及其原理——fast R-CNN,faster R-CNN,YOLO,SSD,YOLOv2,YOLOv3
    hadoop常用命令
    工作流调度系统Azkaban的简介和使用
    java微服务简介与实战
    mxnet快速入门教程
  • 原文地址:https://www.cnblogs.com/kenlig/p/9822594.html
Copyright © 2011-2022 走看看