1. 程式人生 > >HihoCoder 1185 : 連通性·三(強連通縮點)

HihoCoder 1185 : 連通性·三(強連通縮點)

ref name ota while 時間限制 pro int cst str

連通性·三

時間限制: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個整數,最多能夠吃到的牧草數量。

樣例輸入
6 6
2 4 3 5 4 4
1 2
2 4
1 3
3 5
3 6
6 3
樣例輸出
13

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include
<algorithm> #include<vector> using namespace std; #define LL long long const int maxm=200010; int Laxt[maxm],Next[maxm],To[maxm],cnt; int w[maxm],dfn[maxm],low[maxm],times; int q[maxm],head,scc_cnt,scc[maxm],n,instk[maxm]; LL V[maxm],Max; vector<int>G[maxm]; void add(int u,int v) { Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; } void rebuild() { for(int i=1;i<=n;i++){ for(int j=Laxt[i];j;j=Next[j]){ if(scc[i]!=scc[To[j]]){ G[scc[i]].push_back(scc[To[j]]); } } } } void dfs(int u) { instk[u]=1; q[++head]=u; dfn[u]=low[u]=++times; for(int i=Laxt[u];i;i=Next[i]){ int v=To[i]; if(!dfn[v]) { dfs(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_cnt++; while(true){ int x=q[head--]; scc[x]=scc_cnt; V[scc_cnt]+=w[x]; instk[x]=0; if(x==u) break; } } } void dfs2(int u,LL sum) { sum+=V[u]; Max=max(sum,Max); for(int i=0;i<G[u].size();i++){ dfs2(G[u][i],sum); } } int main() { int m,i,u,v; scanf("%d%d",&n,&m); for(i=1;i<=n;i++) scanf("%d",&w[i]); for(i=1;i<=m;i++){ scanf("%d%d",&u,&v); add(u,v); } dfs(1); rebuild(); dfs2(scc[1],0); printf("%lld\n",Max); return 0; }

HihoCoder 1185 : 連通性·三(強連通縮點)