题意:一个人需要联系其他所有人,已知他自己联系每个人的花费,并且他可以联系某个人再让他联系他能联系到的人,给出一系列关系表示 A 能够联系 B。问他最少需要联系多少人,花费多少钱
首先,建成一个有向图,强连通分量内的点可以相互通知,但是如果某个强连通分量入度为0,那么这个强连通分量中的点不能通过其他分量到达,因此只要通知这些入度为0的强连通分量中花费最少的一个人就行了,所以强连通时更新每个分量的最小花费值,然后建边记录入度,联系人数就是入度为0的强连通分量数,而花费就是这些分量的最小花费和。
1 #include2 #include 3 #include 4 #include 5 using namespace std; 6 7 const int maxn=1005; 8 const int maxm=2005; 9 10 int head[2][maxn],point[2][maxm],nxt[2][maxm],size[2];11 int n,t,scccnt;12 int stx[maxn],low[maxn],scc[maxn],num[maxn],a[maxn],id[maxn],ans1,ans2;13 stack S;14 15 void init(){16 memset(head,-1,sizeof(head));17 size[0]=size[1]=0;18 ans1=ans2=0;19 }20 21 void add(int a,int b,int c=0){22 point[c][size[c]]=b;23 nxt[c][size[c]]=head[c][a];24 head[c][a]=size[c]++;25 if(c)id[b]++;26 }27 28 void dfs(int s){29 stx[s]=low[s]=++t;30 S.push(s);31 for(int i=head[0][s];~i;i=nxt[0][i]){32 int j=point[0][i];33 if(!stx[j]){34 dfs(j);35 low[s]=min(low[s],low[j]);36 }37 else if(!scc[j]){38 low[s]=min(low[s],stx[j]);39 }40 }41 if(low[s]==stx[s]){42 scccnt++;43 while(1){44 int u=S.top();S.pop();45 scc[u]=scccnt;46 if(a[u]