题目要求如果输出 NO 的话要在第二行输出最小的不能控制间谍的编号
在我的做法中,我对于缩点后的每个点计算入度,如果这个缩点后的点 入度为 0 且缩点后的点内没有间谍可以贿赂,则将这个缩点后的点内最小的间谍编号与答案的最小取min
我的问题在于:由于我是在入度为0处找编号最小,但如果入度为0这个点没法被贿赂,那这个入度为0连接的后面的点也无法贿赂,怎么保证后面的点中编号都比入度为0的这个点大呢?
Code:
#include<bits/stdc++.h>
#define inf 0x7f7f7f7f
using namespace std;
int n,p,tot,a,b,c,pr[3005],minid[3005],head[3005],ru[3005],cost[3005],dfn[3005],low[3005],color[3005],T,ans,cnt,loss[3005],ANS;
stack<int>s;bool inz[3005];
struct node{
int to,next;
}e[10000005];
void add(int a,int b){
e[++tot].to=b;
e[tot].next=head[a];
head[a]=tot;
}
void tarjan(int v){
dfn[v]=low[v]=++T;inz[v]=1;
s.push(v);
for(int i=head[v];i;i=e[i].next){
int to=e[i].to;
if(!dfn[to])tarjan(to),low[v]=min(low[v],low[to]);
else if(inz[to]) low[v]=min(low[v],dfn[to]);
}
if(dfn[v]==low[v]){
int t;++ans;
do{
t=s.top(),s.pop();inz[t]=0;
cost[ans]=min(cost[ans],pr[t]);
minid[ans]=min(minid[ans],t);
color[t]=ans;
}while(t!=v);
}
}
int main(){
scanf("%d%d",&n,&p);
memset(pr,0x7f,sizeof pr);
memset(cost,0x7f,sizeof cost);
memset(minid,0x7f,sizeof minid);
for(int i=1;i<=p;i++){
scanf("%d%d",&a,&b);
pr[a]=b;
}
scanf("%d",&c);
while(c--){
scanf("%d%d",&a,&b);
add(a,b);
}
for(int i=1;i<=n;i++) if(!dfn[i])tarjan(i);
for(int i=1;i<=n;i++) for(int j=head[i];j;j=e[j].next){
if(color[i]!=color[e[j].to])++ru[color[e[j].to]];
}
bool f=0;int id=inf,all=0;
for(int i=1;i<=ans;i++){
if(ru[i])continue;
if(cost[i]==inf){
f=1; id=min(id,minid[i]);
}
if(!f) all+=cost[i];
}
if(f) printf("NO\n%d",id);
else printf("YES\n%d",all);
return 0;
}