hihoCoder #1185 : 连通性·三(强联通分量+拓扑排序)

#1185 : 连通性·三

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家。今天一大早,约翰因为有事要出去,就拜托小Hi和小Ho忙帮放牧。

约翰家一共有N个草场,每个草场有容量为W[i]的牧草,N个草场之间有M条单向的路径。

小Hi和小Ho需要将牛羊群赶到草场上,当他们吃完一个草场牧草后,继续前往其他草场。当没有可以到达的草场或是能够到达的草场都已经被吃光了之后,小hi和小Ho就把牛羊群赶回家。

一开始小Hi和小Ho在1号草场,在回家之前,牛羊群最多能吃掉多少牧草?

举个例子:

图中每个点表示一个草场,上部分数字表示编号,下部分表示草场的牧草数量w。

在1吃完草之后,小Hi和小Ho可以选择把牛羊群赶到2或者3,假设小Hi和小Ho把牛羊群赶到2:

吃完草场2之后,只能到草场4,当4吃完后没有可以到达的草场,所以小Hi和小Ho就把牛羊群赶回家。

若选择从1到3,则可以到达5,6:

选择5的话,吃完之后只能直接回家。若选择6,还可以再通过6回到3,再到5。

所以该图可以选择的路线有3条:

1->2->4 		total: 11
1->3->5 		total: 9
1->3->6->3->5: 		total: 13
  

所以最多能够吃到的牧草数量为13。

本题改编自USACO月赛金组

提示:强连通分量

输入

第1行:2个正整数,N,M。表示点的数量N,边的数量M。1≤N≤20,000, 1≤M≤100,000

第2行:N个正整数,第i个整数表示第i个牧场的草量w[i]。1≤w[i]≤100,000

第3..M+2行:2个正整数,u,v。表示存在一条从u到v的单向路径。1≤u,v≤N

输出

第1行:1个整数,最多能够吃到的牧草数量。

代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 #include<stack>
 6 #include<queue>
 7 #include<algorithm>
 8 using namespace std;
 9 const int N=2e4+5;
10
11 vector<int>v[N];
12 vector<int>gra[N];
13 stack<int>sk;
14 int n,m,cnt,num,ans;
15 int val[N],low[N],dfn[N],fa[N],sum[N],indeg[N],dp[N];
16 bool vis[N];
17
18 //求出强连通分量
19 void tarjan(int u){
20     low[u]=dfn[u]=++cnt;
21     sk.push(u);
22     for(int i=0;i<v[u].size();i++){
23         int t=v[u][i];
24         if(!dfn[t]){
25             tarjan(t);
26             low[u]=min(low[u],low[t]);
27         }
28         else if(!fa[t]) low[u]=min(low[u],dfn[t]);
29     }
30     if(low[u]==dfn[u]){
31         num++;
32         while(!sk.empty()){
33             int t=sk.top();
34             sk.pop();
35             fa[t]=num;
36             sum[num]+=val[t];
37             if(t==u) break;
38         }
39     }
40 }
41
42 //拓扑排序求最大价值
43 int topo(){
44     queue<int>q;
45     for(int i=1;i<=num;i++){
46         if(indeg[i]==0)
47             q.push(i);
48     }
49     int ans=0;
50     while(!q.empty()){
51         int k=q.front();
52         q.pop();
53         dp[k]+=sum[k];
54         ans=max(dp[k],ans);
55         for(int i=0;i<gra[k].size();i++){
56             int t=gra[k][i];
57             indeg[t]--;
58             dp[t]=max(dp[t],dp[k]);
59             if(indeg[t]==0)
60                 q.push(t);
61         }
62     }
63     return ans;
64 }
65
66 int main(){
67     scanf("%d%d",&n,&m);
68     for(int i=1;i<=n;i++) scanf("%d",&val[i]);
69     for(int i=1;i<=m;i++){
70         int a,b;
71         scanf("%d%d",&a,&b);
72         v[a].push_back(b);
73     }
74     tarjan(1);                  //起点是1
75     //建新图
76     for(int i=1;i<=n;i++){
77         if(fa[i]==0) continue;
78         for(int j=0;j<v[i].size();j++){
79             int t=v[i][j];
80             if(fa[i]!=fa[t])
81                 gra[fa[i]].push_back(fa[t]);
82         }
83     }
84     //计算入度
85     for(int i=1;i<=num;i++){
86         for(int j=0;j<gra[i].size();j++){
87             int t=gra[i][j];
88             indeg[t]++;
89         }
90     }
91     //利用拓扑排序算出答案
92     printf("%d\n",topo());
93     return 0;
94 }

原文地址:https://www.cnblogs.com/fu3638/p/8635548.html

时间: 2024-10-02 15:19:57

hihoCoder #1185 : 连通性·三(强联通分量+拓扑排序)的相关文章

Codeforce 505D - Mr. Kitayuta&#39;s Technology 弱联通分量+拓扑排序

对于有向图M,若将其所有的边转化为无向边,则得到其基图M',若M'是联通的,则称有向图M是弱联通. 对于有向图M,若图中任意两点u,v(u != v)均满足u到v可达,v到u可达,则称此图为强联通. 根据以上定义显然可知,强联通图一定也满足弱联通. 此题首先我们需要找到其所有的弱联通分量. 对于每一个弱联通分量,设此弱联通分量内点的个数为ans,如果此联通分量无环,则需要的边数为ans-1,若有环则为ans. 太挫了,这种题都不会了,怎么变黄!!! #include <algorithm> #

hihoCoder 1185 连通性&#183;三(Tarjan缩点+暴力DFS)

#1185 : 连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出去,就拜托小Hi和小Ho忙帮放牧. 约翰家一共有N个草场,每个草场有容量为W[i]的牧草,N个草场之间有M条单向的路径. 小Hi和小Ho需要将牛羊群赶到草场上,当他们吃完一个草场牧草后,继续前往其他草场.当没有可以到达的草场或是能够到达的草场都已经被吃光了之后,小hi和小Ho就把牛羊群赶回家. 一开

hihocoder #1185 : 连通性&#183;三 tarjan

#1185 : 连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出去,就拜托小Hi和小Ho忙帮放牧. 约翰家一共有N个草场,每个草场有容量为W[i]的牧草,N个草场之间有M条单向的路径. 小Hi和小Ho需要将牛羊群赶到草场上,当他们吃完一个草场牧草后,继续前往其他草场.当没有可以到达的草场或是能够到达的草场都已经被吃光了之后,小hi和小Ho就把牛羊群赶回家. 一开

hihoCoder#1185 : 连通性&#183;三 tarjan求强联通分量 缩点 dfs/拓扑排序求路径和最大值

题目链接: http://hihocoder.com/problemset/problem/1185# 题意: n个点,每个点有一个权值,m条有向边,从1出发,每走到一个点, 就吃掉这个点的草,当没有可以到达的草场或是能够到达的草场都已经被吃光了之后就要返回到1了.求最多可以吃掉多少草. 思路: 提示里面讲的挺好的 如果草场是一个强连通图,那么我们只要走到任意一点,就可以把其他所有的草场都走一遍,并且可以选择任意一个点作为终点.所以把强联通块缩成一个点 因为一个强连通块会被缩成一个点,那么我们可

HihoCoder 1185 : 连通性&#183;三(强连通缩点)

连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出去,就拜托小Hi和小Ho忙帮放牧. 约翰家一共有N个草场,每个草场有容量为W[i]的牧草,N个草场之间有M条单向的路径. 小Hi和小Ho需要将牛羊群赶到草场上,当他们吃完一个草场牧草后,继续前往其他草场.当没有可以到达的草场或是能够到达的草场都已经被吃光了之后,小hi和小Ho就把牛羊群赶回家. 一开始小Hi和小Ho

POJ 2762 Going from u to v or from v to u?(强联通,拓扑排序)

http://poj.org/problem?id=2762 Going from u to v or from v to u? Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14573   Accepted: 3849 Description In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has

POJ 2186-Popular Cows (图论-强联通分量Korasaju算法)

题目链接:http://poj.org/problem?id=2186 题目大意:有n头牛和m对关系, 每一对关系有两个数(a, b)代表a牛认为b牛是“受欢迎”的,且这种关系具有传递性, 如果a牛认为b牛“受欢迎”, b牛认为c牛“受欢迎”, 那么a牛也认为c牛“受欢迎”. 现在想知道有多少头牛受除他本身外其他所有牛的欢迎? 解题思路:如果有两头或者多头牛受除他本身外其他所有牛的欢迎, 那么在这两头或者多头牛之中, 任意一头牛也受两头或者多头牛中别的牛的欢迎, 即这两头或者多头牛同属于一个强联

POJ 2186 Popular cows(Kosaraju+强联通分量模板)

题目链接:http://poj.org/problem?id=2186 题目大意:给定N头牛和M个有序对(A,B),(A,B)表示A牛认为B牛是红人,该关系具有传递性,如果牛A认为牛B是红人,牛B认为牛C是红人,那么牛A也认为牛C是红人.求被其他所有牛认为是红牛的牛的总数. 解题思路:把所有牛看成顶点,把有序对(A,B)看成从A到B的有向边,那么题目就变成了求所有顶点都可到达的顶点的总数.我们可以得到一个结论,如果一个强连通分量里有一头牛被认为是红人,那么该强联通分量里的所有牛都是红人,这显然是

[CF #236 (Div. 2) E] Strictly Positive Matrix(强联通分量)

题目:http://codeforces.com/contest/402/problem/E 题意:给你一个矩阵a,判断是否存在k,使得a^k这个矩阵全部元素都大于0 分析:把矩阵当作01矩阵,超过1的都当作1,那么a矩阵可表示一个有向图的走一次的连通性,则a^k表示有向图走K次的连通性.既然要求最后都没0,即走了K次后,每个点都能互通,这也说明这个图必然是只有一个强联通分量.于是判断k的存在有无,也就是判断a矩阵表示的有向图是不是只有一个强联通分量.