强连通图之HDU1287 Summer Holiday

来源:互联网 发布:android性能优化工具 编辑:程序博客网 时间:2024/05/29 08:21

缩点后得到拓扑图,然后找入度为0的点,最小开销就是联系入度为0的点之和。

#include <stdio.h>#include <ctype.h>#include <string.h>#include <stdlib.h>#include <limits.h>#include <math.h>#include <algorithm>#include <stack>#include <queue>#include <vector>#include <map>#include <set>#include <string>#include <sstream>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1typedef long long LL;const double pi=4.0*atan(1.0);const int MAXN=1005;vector<int> g[MAXN];int dfn[MAXN],lowlink[MAXN],sccno[MAXN],dfs_clock,scc_cnt;stack<int> s;int cost[MAXN];int ans[MAXN];int in[MAXN];void dfs(int u){dfn[u]=lowlink[u]=++dfs_clock;s.push(u);for(int i=0;i<g[u].size();i++){int v=g[u][i];if(!dfn[v]){dfs(v);lowlink[u]=min(lowlink[u],lowlink[v]);}else if(!sccno[v]){lowlink[u]=min(lowlink[u],dfn[v]);}}if(lowlink[u]==dfn[u]){scc_cnt++;while(1){int x=s.top();s.pop();sccno[x]=scc_cnt;if(x==u)break;}}}void Tarjan(int n){dfs_clock=scc_cnt=0;memset(sccno,0,sizeof(sccno));memset(dfn,0,sizeof(dfn));while(!s.empty())s.pop();for(int i=1;i<=n;i++)//下标1到nif(!dfn[i])dfs(i);}int main(){int i,j,k;int T;int n,m;while(scanf("%d%d",&n,&m)!=EOF){for(i=1;i<=n;i++)g[i].clear();for(i=1;i<=n;i++)scanf("%d",cost+i);for(i=1;i<=m;i++){scanf("%d%d",&j,&k);g[j].push_back(k);}Tarjan(n);memset(in,0,sizeof(in));memset(ans,-1,sizeof(ans));for(i=1;i<=n;i++){if(ans[sccno[i]]==-1)ans[sccno[i]]=cost[i];elseans[sccno[i]]=min(ans[sccno[i]],cost[i]);}for(i=1;i<=n;i++)for(j=0;j<g[i].size();j++){int v=g[i][j];if(sccno[v]!=sccno[i])in[sccno[v]]=1;}int a=0,b=0;for(i=1;i<=scc_cnt;i++){if(in[i]==0){a+=ans[i];b++;}}printf("%d %d\n",b,a);}return 0;}


0 0
原创粉丝点击