题目大意;听说lcy帮大家预定了新马泰7日游,Wiskey真是高兴的夜不能寐啊,他想着得快点把这消息告诉大家,虽然他手上有所有人的联系方式,但是一个一个联系过去实在太耗时间和电话费了。他知道其他人也有一些别人的联系方式,这样他可以通知其他人,再让其他人帮忙通知一下别人。你能帮Wiskey计算出至少要通知多少人,至少得花多少电话费就能让所有人都被通知到吗?
Input
多组测试数组,以EOF结束。
第一行两个整数N和M(1<=N<=1000, 1<=M<=2000),表示人数和联系对数。
接下一行有N个整数,表示Wiskey联系第i个人的电话费用。
接着有M行,每行有两个整数X,Y,表示X能联系到Y,但是不表示Y也能联系X。
Output
输出最小联系人数和最小花费。
每个CASE输出答案一行。
//参考了别人的代码。。ya
思路:强连通+缩点...把图缩点成连通分量,找连通分量中入度为0的;再找入度为0 的连通分量中的最小费用。。因为入度为0 的话说明一定要联系其中的一个人。所以找费用最小的
#include <stdio.h>
#include <string.h>
#include <vector>
#include <stack>
using namespace std;
vector<int > p[1002],in[1003],belong[1003];//p[]出度,in【】入度belong[]记录连通分量的值
stack <int >q;
int low[1003],dfn[1003],v[1003],fei[1003],be[1003],mc[1003];//mc最小费用
int sum,now,n,m;
int min(int a,int b)
{
return a>b?b:a;
}
void init()
{
int i;
sum=0;now=1;
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(v,0,sizeof(v));
for(i=0;i<=n;i++)
{mc[i]=10000000;}
for(i=0;i<=n;i++)
{p[i].clear();belong[i].clear();in[i].clear();}
while (!q.empty())
q.pop();
}
void tarjon( int i)
{
int j,t;
v[i]=1;
dfn[i]=low[i]=now++;
q.push(i);
for(j=0;j<p[i].size();j++)
{
t=p[i][j];
if(dfn[t]==0)
{
tarjon(t);
low[i]=min(low[i],low[t]);
}
else if(v[t]==1)
low[i]=min(low[i],dfn[t]);
}
if(dfn[i]==low[i])
{
sum++;
while (!q.empty())
{
j=q.top();
q.pop();
v[j]=0;
belong[sum].push_back(j);
be[j]=sum; //记录j属于哪个连通分量的
if(mc[sum]>fei[j]) mc[sum]=fei[j];
if(j==i) break;
}
}
}
void check()
{
int i,j,k,ii,jj,cnt;
int flag,money=0;
cnt=sum;
for(i=1;i<=cnt;i++)//枚举连通分量
{
flag=0;
for(j=0;j<belong[i].size();j++)//第i个连通分量里存的数
{
k=belong[i][j];
for(ii=0;ii<in[k].size();ii++)//找他的入度是否为0
{
jj=in[k][ii];
if(be[jj]!=i) //不为0,因为jj不属于改模块
{
flag=1;
sum--; // 有入度,所以该模块不需要联系,so--
break;
}
}
if(flag==1) break;
}
if(!flag) money+=mc[i];
}
printf("%d %d\n",sum,money);
}
void judge()
{
int i;
for(i=1;i<=n;i++)
if(dfn[i]==0)
tarjon(i);
check();
}
int main()
{
int i;
int a,b;
// freopen("D://in.txt","r",stdin);
while (scanf("%d%d",&n,&m)!=EOF)
{
init();
for(i=1;i<=n;i++)
scanf("%d",&fei[i]);
for(i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
p[a].push_back(b);
in[b].push_back(a);
}
judge();
}
return 0;
}