from roba
找出强联通分量,然后求出缩点图,找出缩点图内出度为0的点内的原顶点最小的cost值累加
(关于强联通分量前面有文章介绍)
#include <stdio.h>
#include <string.h>
const int N = 10001;
const int M = 200001;
struct e{
int v;
e* next;
};
e* link[N], edge[M], *tlink[N], tedge[M];
int n, m, cost[N], el, tel, f[N], time, belon[N], degree[N], s[N], ans[N];
bool judge[N], zero[N];
void dfs(int v){
int i;e* l = link[v];judge[v] = true;
while(l){
if(!judge[l->v])dfs(l->v);
l = l->next;
}f[v] = time++;
}
void tdfs(int v, int p){
int i;e* l = tlink[v];judge[v] = true;belon[v] = p;
while(l){
if(!judge[l->v])tdfs(l->v, p);
l = l->next;
}
}
int main(){
freopen("2233.in", "r", stdin);
freopen("2233.out", "w", stdout);
int i, j, u, v, fl, out;e* l;
while(scanf("%d%d", &n, &m), m || n){
for(i = time = 0; i < n; i++){tlink[i] = link[i] = NULL;judge[i] = degree[i] = zero[i] = 0;ans[i] = 0x7fffffff;}
for(i = 0; i < n; i++)scanf("%d", &cost[i]);
for(el = tel = 0, i = 0; i < m; i++){
scanf("%d%d", &u, &v);u--;v--;
edge[el].v = v;edge[el].next = link[u];link[u] = &edge[el++];
tedge[tel].v = u;tedge[tel].next = tlink[v];tlink[v] = &tedge[tel++];
}
for(i = 0; i < n; i++)if(!judge[i])dfs(i);
for(i = 0; i < n; i++)s[f[i]] = i;
memset(judge, 0, sizeof(judge));fl = 0;
for(i = n - 1; i >= 0; i--){
if(!judge[s[i]]){
tdfs(s[i], fl++);
}
}
for(i = 0; i < n; i++){
l = link[i];
while(l){
if(belon[i] != belon[l->v])degree[belon[l->v]]++;
l = l->next;
}
}
for(i = 0; i < fl; i++){if(!degree[i]){zero[i] = true;}}
for(i = 0; i < n; i++){
if(zero[belon[i]]){
if(cost[i] < ans[belon[i]])ans[belon[i]] = cost[i];
}
}out = 0;
for(i = 0; i < n; i++){
if(zero[i])out += ans[i];
}
printf("%d\n", out);
}
return 0;
}