HDU3072 Intelligence System

题目传送门

有个中文版的题面...和原题稍有不同

/*
Description
“这一切都是命运石之门的选择。”
试图研制时间机器的机关SERN截获了中二科学家伦太郎发往过去的一条短信,并由此得知了伦太郎制作出了电话微波炉(仮)。
为了掌握时间机器的技术,SERN总部必须尽快将这个消息通过地下秘密通讯网络,传达到所有分部。
SERN共有N个部门(总部编号为0),通讯网络有M条单向通讯线路,每条线路有一个固定的通讯花费Ci。
为了保密,消息的传递只能按照固定的方式进行:从一个已知消息的部门向另一个与它有线路的部门传递(可能存在多条通信线路)。我们定义总费用为所有部门传递消息的费用和。
幸运的是,如果两个部门可以直接或间接地相互传递消息(即能按照上述方法将信息由X传递到Y,同时能由Y传递到X),我们就可以忽略它们之间的花费。
由于资金问题(预算都花在粒子对撞机上了),SERN总部的工程师希望知道,达到目标的最小花费是多少。

Input
多组数据,文件以2个0结尾。
每组数据第一行,一个整数N,表示有N个包括总部的部门(从0开始编号)。然后是一个整数M,表示有M条单向通讯线路。
接下来M行,每行三个整数,Xi,Yi,Ci,表示第i条线路从Xi连向Yi,花费为Ci。

Output
每组数据一行,一个整数表示达到目标的最小花费。

Sample Input
3 3
0 1 100
1 2 50
0 2 100
3 3
0 1 100
1 2 50
2 1 100
2 2
0 1 50
0 1 100
0 0

Sample Output
150
100
50
【样例解释】
第一组数据:总部把消息传给分部1,分部1再传给分部2.总费用:100+50=150.
第二组数据:总部把消息传给分部1,由于分部1和分部2可以互相传递消息,所以分部1可以无费用把消息传给2.总费用:100+0=100.
第三组数据:总部把消息传给分部1,最小费用为50.总费用:50.

Data Constraint
对于10%的数据,保证M=N-1
对于另30%的数据,N ≤ 20 ,M ≤ 20
对于100%的数据,N ≤ 50000 ,M ≤ 10^5 ,Ci ≤ 10^5 ,数据组数 ≤ 5
数据保证一定可以将信息传递到所有部门。

中文题面

初看此题,大概是要在一个有向图里找到从固定点出发遍历每个节点的最小花费

emm...瞬间想到最小生成树,prim大概是有的

"如果两个部门可以直接或间接地相互传递消息,我们就可以忽略它们之间的花费。"

也就是只要有节点形成了环,那么这些节点间通信不要钱...

这不就tarjan缩点过后prim就好了吗...

code了1h,搞出来了,结果发现样例都过不了

原因是prim在无向图里没办法处理权值相同的边

又想了想,缩点后是个DAG图,又保证起始点可以走到所有点,所以对于每一个点,不管它选哪一个入度,都不会影响连通性

那就贪心,对于除起始点的每一个点,取它入度的最小值,然后把所有点加起来就是答案了

这玩意还比prim好写很多

上代码咯

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<ctime>
#include<cstdlib>
#include<queue>
using namespace std;
const int INF=pow(2,31)-1;

struct star {//存边
    int u,v,w;
};
struct Map {//图
    int ptn,edn;
    star edge[200005];//链式前向星存储
    int last[200005],next[200005];
    void mapinit(int pig){//初始化
        ptn=pig;
        edn=0;
    }
    void addedge(int u,int v,int w) {//加边函数
        edn++;
        edge[edn]=(star){u,v,w};
    }
    void starinit() {//前向星初始化
        for(int i=1;i<=ptn;i++) last[i]=-1;
        for(int i=1;i<=edn;i++){
            int flag=edge[i].u;
            next[i]=last[flag];
            last[flag]=i;
        }
    }
}A,B;//A是缩点前的图,B是缩点后的图
int bel[200005];//A中点对应B中哪一个点
int Bn;

int tim;
int dfn[200005],low[200005];
int stack[200005],top;
int isput[200005],t_vis[200005];
void tarjan(int node){//tarjan缩点
    tim++;
    dfn[node]=tim;
    low[node]=tim;
    isput[node]=1;
    t_vis[node]=1;
    stack[top]=node;
    top++;
    for(int i=A.last[node];i!=-1;i=A.next[i]){
        int to=A.edge[i].v;
        if(isput[to]==1){
            low[node]=min(low[node],dfn[to]);
        }else if(t_vis[to]==1){
        }else{
            tarjan(to);
            low[node]=min(low[node],low[to]);
        }
    }
    if(dfn[node]==low[node]){
        Bn++;
        for(;;){
            top--;
            bel[stack[top]]=Bn;
            isput[stack[top]]=0;
            if(stack[top]==node||top==0) break;
        }
    }
}
int ans;
int mn[200005];

int An,Am;
int main() {
    for(;;){
        if(scanf("%d",&An)==EOF)break;
        //input
        scanf("%d",&Am);
        A.mapinit(An);
        for(int i=1;i<=Am;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            u++;v++;
            A.addedge(u,v,w);
        }
        A.starinit();
        //tarjan
        for(int i=1;i<=An;i++) {dfn[i]=0;low[i]=0;t_vis[i]=0;}
        tim=0;
        top=0;
        Bn=0;
        tarjan(1);
        //getB
        B.mapinit(Bn);
        for(int i=1;i<=A.edn;i++){//用A图的强连通分量建B图
            int u=bel[A.edge[i].u],v=bel[A.edge[i].v],w=A.edge[i].w;
            if(u==v) continue;
            B.addedge(u,v,w);
        }
        B.starinit();
        ans=0;
        //getans
        for(int i=1;i<=B.ptn;i++) mn[i]=INF;
        for(int i=1;i<=B.edn;i++){//贪心
            int to=B.edge[i].v;
            mn[to]=min(mn[to],B.edge[i].w);
        }
        mn[bel[1]]=0;//起始点
        for(int i=1;i<=B.ptn;i++){
            ans+=mn[i];
        }
        printf("%d\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/sun123zxy/p/hdu3072.html

时间: 2024-10-14 01:30:56

HDU3072 Intelligence System的相关文章

hdu 3072 Intelligence System

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2909    Accepted Submission(s): 1259 Problem Description After a day, ALPCs finally complete their ultimate intelligence system, the purpose of it

HDU——T 3072 Intelligence System

http://acm.hdu.edu.cn/showproblem.php?pid=3072 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2909    Accepted Submission(s): 1259 Problem Description After a day, ALPCs finally complete their

[tarjan+最小树形图] hdu 3072 Intelligence System

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3072 Intelligence System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1479    Accepted Submission(s): 653 Problem Description After a day, ALP

Intelligence System HDU - 3072(强连通分量)

Intelligence System HDU - 3072 题意:一个人要传递命令给所有人,如果两人之间互达,不需任何费用,求最少费用 有向图强连通. 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int inf=0x3f3f3f3f; 4 const int maxv=50010; 5 const int maxe=100010; 6 int n,m; 7 struct Edge{ 8 int u,v,w; 9 int

Intelligence System (hdu 3072 强联通缩点+贪心)

Intelligence System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1650    Accepted Submission(s): 722 Problem Description After a day, ALPCs finally complete their ultimate intelligence syste

HDU 3072 Intelligence System(强连通+最小树形图)

HDU 3072 Intelligence System 题目链接 题意:给定有向图,边有权值,求保留一些边,从一点出发,能传递到其他所有点的最小代价,保证有解 思路:先缩点,然后从入度为0的点作为起点(因为题目保证有解,所以必然有一个且只有一个入度为0的点),然后做一下最小树形图即可 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #includ

hdoj 3072 Intelligence System【求scc&amp;&amp;缩点】【求连通所有scc的最小花费】

Intelligence System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1904    Accepted Submission(s): 824 Problem Description After a day, ALPCs finally complete their ultimate intelligence system

HDU 3072 Intelligence System (强连通分量)

题目地址:HDU 3072 这题一开始理解错题目意思了..(不得不吐槽一下题目意思确实不好理解..)用的强连通+最小生成树做的...然后错了好多遍...sad..题目意思是从一个给定点向其他所有点通信的最少花费,那么入度为0的点肯定是那个给定点.然后对于其它点,枚举就好了.找一个到他花费最少的点的花费. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue&g

HDU - 3072 Intelligence System(强连通分量+类最小生成树)

题目大意:有一个人想要将消息告诉给所有人(在同一个强连通分量里面的人可以相互转告,费用为0),问所有人都知道消息的最小花费是多少 解题思路:求出所有的强连通分量,然后将其缩点,桥就是连接其中的边 因为是张连通图,所以只要求出每个强连通分量被通知的最小价值,然后累加即可 刚开始以为可以用最小生成树,但发现错了,假设求出了三个强连通分量了,分别标号为1,2,3 再给出桥 1-2,权值1,1-3权值5,3-2权值4 按最小生成树的话,得到的结果是5,然而并不是这样的,因为是有向边,所以3这个点是不会被