先縮點,若是縮完點的全部入度爲零的點均可以被收買ios
那麼總代價就是收買他們的代價之和spa
反之不能所有收買code
在實現的時候ci
for(int i=1; i<=n; i++) if(!dfn[i]&&money[i]!=2139062143) tarjan(i);
是爲了防止一個不肯意被收買的人成爲根(也許吧)string
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<stack> using namespace std; int money[10010]; int from[10010],to[10010],nex[10010],head[10010]; int dfn[10010],low[10010],scc[10010],scce[10010],sccm[10010],dfsn,sccn; int instack[10010],ans; stack <int> s; void tarjan(int u) { dfn[u]=low[u]=++dfsn; instack[u]=true; s.push(u); for(int i=head[u]; i; i=nex[i]) { if(!dfn[to[i]]) { tarjan(to[i]); low[u]=min(low[u],low[to[i]]); } else if(instack[to[i]]) low[u]=min(low[u],dfn[to[i]]); } if(dfn[u]==low[u]) { int v; ++sccn; do { v=s.top(); s.pop(); scc[v]=sccn; sccm[sccn]=min(sccm[sccn],money[v]); instack[v]=false; } while(u!=v); } return ; } int main() { ios::sync_with_stdio(false); memset(sccm,0x7f,sizeof(sccm)); memset(money,0x7f,sizeof(money)); int n,p,x,y; cin>>n>>p; for(int i=1; i<=p; i++) { cin>>x>>y; money[x]=y; } cin>>p; for(int i=1; i<=p; i++) { cin>>x>>y; from[i]=x; to[i]=y; nex[i]=head[x]; head[x]=i; } for(int i=1; i<=n; i++) if(!dfn[i]&&money[i]!=2139062143) tarjan(i); for(int i=1; i<=n; i++) if(!dfn[i]) { cout<<"NO"<<endl; cout<<i; return 0; } for(int i=1; i<=n; i++) for(int j=head[i]; j; j=nex[j]) if(scc[i]!=scc[to[j]]) scce[scc[to[j]]]++; for(int i=1; i<=sccn; i++) if(scce[i]==0) ans+=sccm[i]; cout<<"YES"<<endl; cout<<ans; return 0; }