题意是有一堆人,和若干关系(单向),你假如选择了一个人,那么其他可以传递的都不需要花费就可以得到。。问最小花费和最少选择人数。。
是一个求强连通的题目,因为如果我们把强连通分量缩点了以后,那么其实就是要把入度为0的都选了就可以,注意如果入度为0的是一个缩点就再枚举找一下里面最小的。。
接下来就是很显然了,这里套用kuangbin的模板。。第一次做强连通,没有想到缩点,用了个奇怪的姿势水过。。。后来想了想应该是错误的?大概是数据比较弱。
ac代码(可能有错误,主要练习一下 tarjan。。。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
int n,m,a,b;
const int MAXN = 1005;
const int MAXM = 2005;
vector<int> E[MAXN];
struct Edge{
int to,next;
} edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];
int Index,top,scc;
bool Instack[MAXN];
int num[MAXN];
void addedge(int u,int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void Tarjan(int u){
int v;
Low[u] = DFN[u] = ++Index;
Stack[top++] = u;
Instack[u] = true;
for(int i = head[u]; i != -1; i = edge[i].next){
v = edge[i].to;
if( !DFN[v] ){
Tarjan(v);
if( Low[u] > Low[v] )Low[u] = Low[v];
}
else if(Instack[v] && Low[u] > DFN[v]) Low[u] = DFN[v];
}
if(Low[u] == DFN[u]){
scc++;
do{
v = Stack[--top];
Instack[v] = false;
Belong[v] = scc;
num[scc]++;
}
while( v != u);
}
}
void solve(int N){
memset(DFN,0,sizeof(DFN));
memset(Instack,false,sizeof(Instack));
memset(num,0,sizeof(num));
Index = scc = top = 0;
for(int i = 1; i <= N; i++) if(!DFN[i]) Tarjan(i);
}
void init(){
tot = 0;
memset(head,-1,sizeof(head));
}
int arr[MAXN];
int vis[MAXN];
vector<int> be[MAXN];
pair<int,int> in[MAXN];
void dfs(int x){
vis[x]=1;
for(int i=0;i<E[x].size();i++){
if(!vis[E[x][i]])
dfs(E[x][i]);
}
}
int main()
{
while(~scanf("%d%d",&n,&m)){
init();
memset(in,0,sizeof(in));
memset(vis,0,sizeof(vis));
for(int i=0;i<=n;i++) E[i].clear();
for(int i=0;i<=n;i++) be[i].clear();
for(int i=1;i<=n;i++) scanf("%d",&arr[i]);
for(int i=1;i<=n;i++) in[i].second=i;
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
addedge(a,b);
E[a].push_back(b);
++in[b].first;
}
solve(n);
sort(in+1,in+n+1);
int ans=0,cnt=0,ad=0;
for(int i=1;i<=n;i++){
be[Belong[i]].push_back(i);
}
for(int i=1;i<=n;i++){
if(vis[in[i].second]==1||(in[i].first!=0&&num[Belong[in[i].second]]==1))
continue;
++cnt;
ad=arr[in[i].second];
for(int j=0;j<be[Belong[in[i].second]].size();j++){
ad=min(ad,arr[be[Belong[in[i].second]][j]]);
}
ans+=ad;
dfs(in[i].second);
}
printf("%d %d
",cnt,ans);
}
return 0;
}