• HDU


    <题目链接>

    题目大意:

    听说lcy帮大家预定了新马泰7日游,Wiskey真是高兴的夜不能寐啊,他想着得快点把这消息告诉大家,虽然他手上有所有人的联系方式,但是一个一个联系过去实在太耗时间和电话费了。他知道其他人也有一些别人的联系方式,这样他可以通知其他人,再让其他人帮忙通知一下别人。你能帮Wiskey计算出至少要通知多少人,至少得花多少电话费就能让所有人都被通知到吗? 

    解题分析:

    强连通缩点,再将所有入度为0的强连通分量中最小的价值相加即可。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define pb push_back
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define clr(a,b) memset(a,b,sizeof(a))
    const int N = 1e3+10,M = 2e3+10;
    int n,m,tot,cnt,scc,top;
    int val[N],instk[N],stk[N],dfn[N],low[N],ind[N],outd[N],belong[N],head[N];
    struct Edge{
        int to,next;
    }edge[M];
    vector<int>G[N];
    void init(){
        rep(i,0,n)G[i].clear();
        tot=cnt=scc=top=0;
        clr(instk,0);clr(stk,0);clr(dfn,0);clr(low,0);clr(ind,0);clr(outd,0);clr(belong,0),clr(head,-1);
    }
    void addedge(int u,int v){
        edge[++cnt].to=v,edge[cnt].next=head[u];
        head[u]=cnt;
    }
    void Tarjan(int u){
        dfn[u]=low[u]=++tot;
        stk[++top]=u;instk[u]=1;
        for(int i=head[u];~i;i=edge[i].next){
            int v=edge[i].to;
            if(!dfn[v]){
                Tarjan(v);
                low[u]=min(low[u],low[v]);
            }else if(instk[v])low[u]=min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u]){
            scc++;
            while(true){
                int v=stk[top--];
                instk[v]=0;
                belong[v]=scc;
                G[scc].pb(v);
                if(v==u)break;
            }
        }
    }
    int main(){
        while(scanf("%d%d",&n,&m)!=EOF){
            init();
            rep(i,1,n)scanf("%d",&val[i]);
            rep(i,1,m){
                int u,v;scanf("%d%d",&u,&v);
                addedge(u,v);
            }
            rep(i,1,n)
                if(!dfn[i])Tarjan(i);
            rep(u,1,n) for(int i=head[u];~i;i=edge[i].next){
                int v=edge[i].to;
                if(belong[u]!=belong[v])
                    ind[belong[v]]++,outd[belong[u]]++;
            }
            int ans=0,res=0;
            rep(i,1,scc) if(!ind[i]){
                int mn=1e9;
                rep(j,0,G[i].size()-1){      //遍历该连通块中的所有元素,寻找价值最小的
                    int v=G[i][j];
                    mn=min(mn,val[v]);
                }
                res++;
                ans+=mn;
            }
            printf("%d %d
    ",res,ans);
        }
    }
  • 相关阅读:
    SQL随机生成6位数字
    安装时提示 INSTALL_PARSE_FAILED_MANIFEST_MALFORMED 解决办法
    Windows 7 完美安装 Visual C++ 6.0
    解决js中window.location.href不工作的问题
    DataList中动态显示DIV
    Gridview、DataList、Repeater获取行索引号
    Java多jdk安装
    【CentOS】samba服务器安装与配置
    【CentOS】IBM X3650M4 IMM远程管理【转载】
    【Java】Eclipse导出jar包与javadoc
  • 原文地址:https://www.cnblogs.com/00isok/p/10765315.html
Copyright © 2020-2023  润新知