12 16 2 2 2 2 2 2 2 2 2 2 2 2 1 3 3 2 2 1 3 4 2 4 3 5 5 4 4 6 6 4 7 4 7 12 7 8 8 7 8 9 10 9 11 10
3 6
先求出强连通分量,然后把各个强连通分量缩成一个点判断这个点的度
当度为0的时候说明要通知,然后在求期间的费用
ACcode:
#include <map> #include <queue> #include <cmath> #include <cstdio> #include <cstring> #include <stdlib.h> #include <iostream> #include <algorithm> #define maxn 10000 using namespace std; struct Edge{ int to,next; }edge[maxn]; int head[maxn],tot; int low[maxn],dfn[maxn],Stack[maxn],Belong[maxn]; int Index,top; int scc; bool Instack[maxn]; int num[maxn]; int cost[maxn]; int rdu[maxn]; void add(){ int u,v; scanf("%d%d",&u,&v); edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } void tarjan(int u){ int v; low[u]=dfn[u]=++Index; Stack[top++]=u; Instack[u]=true; for(int i=head[u];i!=-1;i=edge[i].next){ v=edge[i].to; if(!dfn[v]){ tarjan(v); if(low[u]>low[v])low[u]=low[v]; } else if(Instack[v]&&low[u]>dfn[v]) low[u]=dfn[v]; } if(low[u]==dfn[u]){ scc++; do{ v=Stack[--top]; Instack[v]=false; Belong[v]=scc; num[scc]++; } while(v!=u); } } void solve(int n){ for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i); int ans,mcost,v; ans=mcost=0; for(int i=1;i<=n;++i){ for(int k=head[i];k!=-1;k=edge[k].next){ v=edge[k].to; if(Belong[i]!=Belong[v]) rdu[Belong[v]]++; } } for(int i=1;i<=scc;++i) if(!rdu[i]){ ans++; int minn=9999999999; for(int k=1;k<=n;++k) if(Belong[k]==i) minn=minn>cost[k]?cost[k]:minn; // cout<<minn<<'\12'; mcost+=minn; } printf("%d %d\n",ans,mcost); } void init(){ memset(head,-1,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(Instack,0,sizeof(Instack)); memset(num,0,sizeof(num)); memset(rdu,0,sizeof(rdu)); memset(Belong,0,sizeof(Belong)); Index=scc=top=tot=0; } int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ init(); for(int i=1;i<=n;i++)scanf("%d",&cost[i]); for(int i=0;i<m;i++)add(); solve(n); } return 0; } /* 12 16 2 2 2 2 2 2 2 2 2 2 2 2 1 3 3 2 2 1 3 4 2 4 3 5 5 4 4 6 6 4 7 4 7 12 7 8 8 7 8 9 10 9 11 10 */