#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个整数,最多能够吃到的牧草数量。

代码

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<queue>
#include<algorithm>
using namespace std;
const int N=2e4+; vector<int>v[N];
vector<int>gra[N];
stack<int>sk;
int n,m,cnt,num,ans;
int val[N],low[N],dfn[N],fa[N],sum[N],indeg[N],dp[N];
bool vis[N]; //求出强连通分量
void tarjan(int u){
low[u]=dfn[u]=++cnt;
sk.push(u);
for(int i=;i<v[u].size();i++){
int t=v[u][i];
if(!dfn[t]){
tarjan(t);
low[u]=min(low[u],low[t]);
}
else if(!fa[t]) low[u]=min(low[u],dfn[t]);
}
if(low[u]==dfn[u]){
num++;
while(!sk.empty()){
int t=sk.top();
sk.pop();
fa[t]=num;
sum[num]+=val[t];
if(t==u) break;
}
}
} //拓扑排序求最大价值
int topo(){
queue<int>q;
for(int i=;i<=num;i++){
if(indeg[i]==)
q.push(i);
}
int ans=;
while(!q.empty()){
int k=q.front();
q.pop();
dp[k]+=sum[k];
ans=max(dp[k],ans);
for(int i=;i<gra[k].size();i++){
int t=gra[k][i];
indeg[t]--;
dp[t]=max(dp[t],dp[k]);
if(indeg[t]==)
q.push(t);
}
}
return ans;
} int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%d",&val[i]);
for(int i=;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
v[a].push_back(b);
}
tarjan(); //起点是1
//建新图
for(int i=;i<=n;i++){
if(fa[i]==) continue;
for(int j=;j<v[i].size();j++){
int t=v[i][j];
if(fa[i]!=fa[t])
gra[fa[i]].push_back(fa[t]);
}
}
//计算入度
for(int i=;i<=num;i++){
for(int j=;j<gra[i].size();j++){
int t=gra[i][j];
indeg[t]++;
}
}
//利用拓扑排序算出答案
printf("%d\n",topo());
return ;
}

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

  1. hihoCoder 1185 连通性·三(Tarjan缩点+暴力DFS)

    #1185 : 连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出 ...

  2. HihoCoder 1185 : 连通性·三(强连通缩点)

    连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出去,就拜托小Hi ...

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

    id=2762">http://poj.org/problem?id=2762 Going from u to v or from v to u? Time Limit: 2000MS ...

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

    题目链接:http://poj.org/problem?id=2186 题目大意:有n头牛和m对关系, 每一对关系有两个数(a, b)代表a牛认为b牛是“受欢迎”的,且这种关系具有传递性, 如果a牛认 ...

  5. CodeForces 1213F (强联通分量分解+拓扑排序)

    传送门 •题意 给你两个数组 p,q ,分别存放 1~n 的某个全排列: 让你根据这两个数组构造一个字符串 S,要求: (1)$\forall i \in [1,n-1],S_{pi}\leq S _ ...

  6. Kosaraju算法---强联通分量

    1.基础知识 所需结构:原图.反向图(若在原图中存在vi到vj有向边,在反向图中就变为vj到vi的有向边).标记数组(标记是否遍历过).一个栈(或记录顶点离开时间的数组).      算法描叙: :对 ...

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

    题目:http://codeforces.com/contest/402/problem/E 题意:给你一个矩阵a,判断是否存在k,使得a^k这个矩阵全部元素都大于0 分析:把矩阵当作01矩阵,超过1 ...

  8. 强联通分量-tarjan算法

    定义:在一张有向图中,两个点可以相互到达,则称这两个点强连通:一张有向图上任意两个点可以相互到达,则称这张图为强连通图:非强连通图有极大的强连通子图,成为强联通分量. 如图,{1},{6}分别是一个强 ...

  9. POJ 2186 强联通分量

    点击打开链接 题意:牛A喜欢牛B,若牛B喜欢牛C,则牛A喜欢牛C,问最后多少牛被其它全部牛喜欢 思路:用强联通分量进行缩点,最后形成的图是有向无环图DAG.而拓扑序的值为DAG的长度,则加一,可是最后 ...

随机推荐

  1. Codeforces 804D Expected diameter of a tree

    D. Expected diameter of a tree time limit per test 3 seconds memory limit per test 256 megabytes inp ...

  2. js 字符串格式化

    在js 文件中写一个函数 String.prototype.format = function(args) { var result = this; if (arguments.length > ...

  3. DBMS_RANDOM 用法

    oracle中用于生成随机数的包:DBMS_RANDOM,这个包里面包含了很多方法,以下列出几个常用的方法 1.DBMS_RANDOM.RANDOM方法: FUNCTION random RETURN ...

  4. 3.Filter和interceptor的区别

    https://blog.csdn.net/qq_36411874/article/details/53996873

  5. bzoj千题计划158:bzoj2406: 矩阵(有源汇上下界可行流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2406 设矩阵C=A-B 最小化 C 一行或一列和的最大值 整体考虑一行或者一列的和 二分最大值 这样 ...

  6. 半小时让你成为EXCEL高手

  7. Java并发编程原理与实战二十二:Condition的使用

    Condition的使用 Condition用于实现条件锁,可以唤醒指定的阻塞线程.下面来实现一个多线程顺序打印a,b,c的例子. 先来看用wait和notify的实现: public class D ...

  8. 经典Dialog插件Layer

    Github上只有一个test,所以最好还是到官网去学习,官网的示例写的很详尽,难得一见的设计思路和灵活性都极好的插件.下面是我自己test过的demo <!DOCTYPE html> & ...

  9. select 函数小结 -- 转自百度知道

    http://zhidao.baidu.com/link?url=UVTXeK4ncKmnwatGUW2deMFylNYBuur-zHmK3w53NXNRpgPbhld2WdkMD766nKl_6Hj ...

  10. HDU 1556 Color the ball (树状数组 区间更新+单点查询)

    题目链接 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽&quo ...