zoukankan      html  css  js  c++  java
  • CodeForces

    嘛,首先把图缩点一下之后就很好搞了

    考虑一下,什么情况下可以使得加边最少,并且s可以把所有点遍历到?

    很显然,对于一个入度不为0的点,一定有前继节点....

    于是乎,我们只要找到不满足有前继节点的节点就好了

    详细的过程看代码...

    #include<bits/stdc++.h>
    #define MAXN 5005
    using namespace std;
    
    int n,m,tot,tot2,dx,tx;
    int s,p,ed;
    int sum;
    int in[MAXN];
    int h[MAXN],h2[MAXN],low[MAXN],dfn[MAXN],belong[MAXN];
    bool vis[MAXN];
    stack<int>q;
    
    struct node{
        int from,to,next;
    }e[MAXN<<1],e2[MAXN<<1];
    
    void init(){
        tot = tot2 = dx = tx = sum = 0;
        memset(h,-1,sizeof(h));
        memset(h2,-1,sizeof(h2));
        memset(dfn,0,sizeof(dfn));
        memset(in,0,sizeof(in));
        memset(low,0,sizeof(low));
        memset(vis,false,sizeof(vis));
    }
    
    void add(int x,int y){
        tot++;
        e[tot].from = x;
        e[tot].to = y;
        e[tot].next = h[x];
        h[x] = tot;
    }
    
    void add2(int x,int y){
        tot2++;
        e2[tot2].from = x;
        e2[tot2].to = y;
        e2[tot2].next = h2[x];
        h2[x] = tot2;
    }
    
    int tarjan(int now){
        dx++;
        low[now] = dfn[now] = dx;
        q.push(now),vis[now] = true;
        for(int i = h[now];i != (-1);i = e[i].next){
            if(!dfn[e[i].to]){
                tarjan(e[i].to);
                low[now] = min(low[now] , low[e[i].to]);
            }
            else if(vis[e[i].to]){
                low[now] = min(low[now] , dfn[e[i].to]);
            }
        }
        if(dfn[now]==low[now]){
            int u;
            tx++;
            do{
                u = q.top();
                belong[u] = tx;
                q.pop();
                vis[u] = false;
            }while(u!=now);
        }
    }
    
    void solve(){
        for(int i = 1;i<=tx;i++){
            if(!in[i]&&i != belong[s]){
                sum++;
                in[i]++;
            }
        }
        cout<<sum<<endl;
    }
    
    int main(){
        init();
        cin>>n>>m>>s;
        for(int i = 1;i<=m;i++){
            int x,y;cin>>x>>y;
            add(x,y);
        }
        for(int i = 1;i<=n;i++)
            if(!dfn[i])tarjan(i);
        for(int i = 1;i<=m;i++){
            if(belong[e[i].from] == belong[e[i].to])continue;
            add2(belong[e[i].from] , belong[e[i].to]);
            in[belong[e[i].to]]++;
        }
        solve();
    }
    View Code
  • 相关阅读:
    操作系统精髓读书笔记
    springboot 项目中读取资源文件内容 如图片、文档文件
    重构-改善既有代码的设计读书小结
    投资中最简单的事读书笔记
    公司的行业差异
    Linux-TCP之深入浅出send和recv
    Linux-socket的close和shutdown区别及应用场景
    C-pthread_cond_wait 详解
    Linux-文件描述符的本质及与文件指针的区别
    数据结构-树的进化及与数据库的关系
  • 原文地址:https://www.cnblogs.com/shatianming/p/12328957.html
Copyright © 2011-2022 走看看