#include<iostream> #include<algorithm> #include<stdio.h> #include<string.h> using namespace std; #define DEBUG if(1) const int MAXN = 1010;//点数 const int MAXM = 2010;//边数 class POINT{public: int next[MAXM],num,DFN,Low,Instack,Belong; void RESET(){//Belong的值是1~scc num=0;DFN=Instack=0; } void add(int b){ next[num++]=b; } }P[MAXN]; int head[MAXN],N,M,Stack[MAXN]; int Index,top; int scc;//强连通分量的个数 bool Instack[MAXN]; int num[MAXN]; //各个强连通分量包含点的个数,数组编号1~scc //num数组不一定需要,结合实际情况 void Tarjan(int u){ int v; P[u].Low = P[u].DFN = ++Index; Stack[top++] = u; P[u].Instack = true; for(int i=0;i<P[u].num;i++){//遍历所有下一节点 v = P[u].next[i]; if( !P[v].DFN ){ Tarjan(v); if( P[u].Low > P[v].Low )P[u].Low = P[v].Low;//使可回溯最初始点最小 }else if(P[v].Instack && P[u].Low > P[v].DFN)//遍历到遍历过的点 P[u].Low = P[v].DFN;//说明循环了,记录 } if(P[u].Low == P[u].DFN){ //最小可回溯点与当前点编号相等说明该点是一个强联通子图初始点 scc++; do{ v = Stack[--top]; P[v].Instack = false; P[v].Belong = scc;//该点所属子图编号 num[scc]++; }while( v != u); } } void solve(int N){ for(int i = 1; i <= N; i++) if(!P[i].DFN)//确保遍历所有节点 Tarjan(i); } int main(){ int fee[MAXN]; memset(fee,0,sizeof(fee)); while(cin>>N>>M){ if(M==0||N==0)break; memset(num,0,sizeof(num)); Index = scc = top = 0;//初始化 for(int i=1;i<=N;i++)P[i].RESET(); for(int i=1;i<=N;i++)scanf("%d",&fee[i]); for(int i=0;i<M;i++){ int a,b;cin>>a>>b; P[a].add(b);//加入边 } solve(N); int mfee[MAXN]={0}; //记录每个强连通图集的最小话费 bool inode[MAXN]={false}; //不可达连通图 int cnt=0;//记录多少个不可达连通图 DEBUG{ for(int i=1;i<N;i++){ POINT & t=P[i];//输出所有节点的编号等 cout<<i<<" DFN="<<t.DFN <<" Low="<<t.Low <<" Belong="<<t.Belong <<endl; for(int j=0;j<t.num;j++){ cout<<"\t->"<<t.next[j]<<endl; } } } for(int i=0;i<=N;i++){ POINT & t=P[i]; for(int j=0;j<t.num;j++){ int tt=P[t.next[j]].Belong; if(t.Belong!=tt){ //当前点与下一点所属强联通子图编号不同 //说明下一强联通子图需要另算费用 inode[tt]=true; } } } for(int i=1;i<=scc;i++){ if(!inode[i]) cnt++; mfee[i]=1e9; } for(int i=1;i<=N;i++){ int t=P[i].Belong; if(!inode[t]) mfee[t]=min(mfee[t],fee[i]); } int sum=0; for(int i=1;i<=scc;i++) if(mfee[i]!=1e9) sum+=mfee[i]; printf("%d %d\n",cnt,sum); } return 0; }
https://vjudge.net/contest/382410#problem/E