33,008
社区成员
发帖
与我相关
我的任务
分享
#include<iostream>
using namespace std;
struct Node
{
int num;
Node* next;
};
const int MAXN=10000;
Node node1[MAXN+1],node2[MAXN+1];//两个邻接表,一个正向,一个逆向
int visit[MAXN+1];
int degree[MAXN+1];//记录每个点的入度
int order[MAXN+1];//记录dfs过程结束访问点的顺序
int part[MAXN+1];//记录哪个点属于哪个强连通分量,比如part[i]==ans,则点i属于第ans个强连通分量
int mincost[MAXN+1];//记录每个强连通分量中花费最小的点
int cost[MAXN+1];//记录每个点的花费
int cnt[MAXN+1];//记录每个强连通分量中有几个点,比如cnt[i]==j,则第i个强连通分量有j个点
int ans;
int t;
void DFS1(int i)
{
if(visit[i]==1)
return ;
visit[i]=1;
Node* p=node1[i].next;
while(p)
{
DFS1(p->num);
p=p->next;
}
order[++t]=i;
}
void DFS2(int i)
{
if(visit[i]==1)
return ;
visit[i]=1;
Node* p=node2[i].next;
while(p)
{
DFS2(p->num);
p=p->next;
}
part[i]=ans;
cnt[ans]++;
if(cost[i]<mincost[ans])
mincost[ans]=cost[i];
}
int main()
{
int n,m;
while(cin>>n>>m)
{
if(n==0&&m==0)
break;
memset(visit,0,sizeof(visit));
memset(part,0,sizeof(part));
memset(degree,0,sizeof(degree));
memset(node1,0,sizeof(node1));
memset(node2,0,sizeof(node2));
memset(cnt,0,sizeof(cnt));
int i,j;
for(i=1;i<=n;i++)
mincost[i]=10010;
for(i=1;i<=n;i++)
{
node1[i].next=NULL;
node2[i].next=NULL;
}
for(i=1;i<=n;i++)
cin>>cost[i];
Node* p;
for(i=1;i<=m;i++)
{
p=new Node;
int s,t;
cin>>s>>t;
degree[t]++;
p->num=t;
p->next=node1[s].next;
node1[s].next=p;
p=new Node;
p->num=s;
p->next=node2[t].next;
node2[t].next=p;
}
t=0;
for(i=1;i<=n;i++)
{
if(!visit[i])
DFS1(i);
}
memset(visit,0,sizeof(visit));
ans=0;
for(i=n;i>=1;i--)
{
if(!visit[order[i]])
{
ans++;
DFS2(order[i]);
}
}
int tot=0;
for(i=1;i<=ans;i++)
{
if(cnt[i]==1)
{
for(j=1;j<=n;j++)
{
if(part[j]==i)
break;
}
if(degree[j]==0)
tot+=cost[j];
}
else
{
tot+=mincost[i];
}
}
cout<<tot<<endl;
}
return 0;
}