HDU 3072 图论scc

 1 #include<bits/stdc++.h>
 2 #define INF 0x7fffffff
 3 using namespace std;
 4 const int MAXN = 50010;//点数
 5 const int MAXM = 100100;//边数
 6 struct Edge {
 7     int to,next,val;
 8 }edge[MAXM];
 9 int head[MAXN],tot,a,b;
10 int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~scc
11 int Index,top; int scc;//强连通分量的个数
12 int in[MAXN],out[MAXN],val[MAXN],d[MAXN];
13 bool Instack[MAXN];
14 int num[MAXN];//各个强连通分量包含点的个数,数组编号1~scc //num数组不一定需要,结合实际情况
15 int cnt=0,ans=0;
16 void addedge(int u,int v,int w){
17     edge[tot].to = v;
18     edge[tot].next = head[u];
19     edge[tot].val=w;
20     head[u] = tot++;
21 }
22 void Tarjan(int u){
23     int v;
24     Low[u] = DFN[u] = ++Index;
25     Stack[top++] = u;
26     Instack[u] = true;
27     for(int i = head[u];i != -1;i = edge[i].next) {
28         v = edge[i].to;
29         if( !DFN[v] ){
30             Tarjan(v);
31             if( Low[u] > Low[v] )
32                 Low[u] = Low[v];
33         }
34         else if(Instack[v] && Low[u] > DFN[v])
35             Low[u] = DFN[v];
36         }
37         if(Low[u] == DFN[u]){
38             scc++;
39             do{
40                 v = Stack[--top];
41                 Instack[v] = false;
42                 Belong[v] = scc;
43                 num[scc]++;
44             }while( v != u);
45         }
46 }
47 void find_val(int u){
48     int v;
49     for(int i = head[u];i != -1;i = edge[i].next){
50         v = edge[i].to;
51         if(Belong[u]==Belong[v]) continue;
52         val[Belong[v]]=min(val[Belong[v]],edge[i].val);
53         //out[Belong[u]]++;
54     }
55 }
56 void solve(int N){
57     memset(DFN,0,sizeof(DFN));
58     memset(Instack,false,sizeof(Instack));
59     memset(num,0,sizeof(num));
60     Index = scc = top = 0;
61     for(int i=1;i<=N;i++) val[i]=INF;
62     for(int i = 1;i <= N;i++)
63         if(!DFN[i])
64         Tarjan(i);
65     for(int i=1;i<=N;i++){
66     //    val[Belong[i]]=min(val[Belong[i]],d[i]);
67         find_val(i);
68     }
69     val[Belong[1]]=0;
70     for(int i=1;i<=scc;i++){
71         ans+=val[i];
72     }
73 }
74 void init(){
75     tot = 0;
76     cnt=0,ans=0;
77     memset(head,-1,sizeof(head));
78     memset(in,0,sizeof(in));
79     memset(out,0,sizeof(out));
80 }
81 int main(){
82     int n,m,u,v,w,T;
83     while(scanf("%d%d",&n,&m)!=EOF){
84         init();
85         //for(int i=1;i<=n;i++) scanf("%d",&d[i]);
86         for(int i=1;i<=m;i++){
87             scanf("%d%d%d",&u,&v,&w);
88             u++,v++;
89             addedge(u,v,w);
90         }
91         solve(n);
92         cout<<ans<<endl;
93         //cout<<cnt<<‘ ‘<<ans<<endl;
94     }
95     return 0;
96 }
时间: 2024-07-28 14:49:40

HDU 3072 图论scc的相关文章

hdu 3072 有向图缩点成最小树形图计算最小权

题意,从0点出发,遍历所有点,遍历边时候要付出代价,在一个SCC中的边不要付费.求最小费用. 有向图缩点(无需建立新图,,n<=50000,建则超时),遍历边,若不在一个SCC中,用一个数组更新记录最小到达该连通分量的最小边权即可...边聊天,边1A,哈哈... #include<iostream> #include<stack> #include<queue> #include<cstdio> #include<cstring> usin

HDU 3072 Intelligence System (强连通分量)

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

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

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

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

HDU 2767 Proving Equivalences 图论scc缩点

问一个图,最少需要加多少条边,使得这个图强联通. Tarjan缩点,重建图,令a=入度为0的scc个数,b=出度为0的scc个数,ans=max(a,b): 若图scc=1,本身强联通,ans=0: 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXN = 20010;//点数 4 const int MAXM = 200100;//边数 5 struct Edge { 6 int to,next; 7 }edge[

HDU 3072 SCC Intelligence System

给出一个带权有向图,要使整个图连通.SCC中的点之间花费为0,所以就先缩点,然后缩点后两点之间的权值为最小边的权值,把这些权值累加起来就是答案. 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <vector> 6 #include <stack> 7 using namespace std

[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

HDU 5521 [图论][最短路][建图灵感]

/* 思前想后 还是决定坚持写博客吧... 题意: n个点,m个集合.每个集合里边的点是联通的且任意两点之间有一条dis[i]的边(每个集合一个dis[i]) 求同时从第1个点和第n个点出发的两个人相遇的最短时间,并输出相遇的地点,如果有多个按编号大小顺序输出. 输入: 测试数据 t n m 以下m行每行 dis[i] 该集合点的数量 ...每个点的标号 数据范围: n 2-1e5 所有集合的元素的数量和 1e6 思路: 如果直接跑最短路,边会存爆的. 考虑换种思路建边. 每个集合看作两个点,一

HDU 3072 Intelligence System (强连通+(贪心||树形图))

大意:在一个联通分量里面的边权值忽略不计,求缩点后的所有联通分量链接在一起的最小权值和. 思路:必然先缩点,最后得到的图为DAG,然后就是统计权值,对于那么到达当前的缩点可能有多个入度,所以选择最小的即可.最后避开起始点的dis[star] == inf.累加即可. #include<map> #include<queue> #include<cmath> #include<cstdio> #include<stack> #include<