P1262 间谍网络
Tarjan缩点
我们用Tarjan缩完点后,剩下若干个DAG图。
我们发现,只要每个图的根所对应的强连通分量上有某人能被收买,显然整个DAG上的人都能被收买。
于是我们就在Tarjan的过程中顺便维护每个强连通分量的对应最小费用,也就是分量中价格最便宜的那个人。
(终于找到我会写的题了qwq)
#include<iostream> #include<cstdio> #include<cstring> #include<cctype> using namespace std; template <typename T> inline T min(T &a,T &b) {return a<b ? a:b;} template <typename T> inline void read(T &x){ char c=getchar(); x=0; while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar(); } int n,m1,m2,ans,dfs_clock,dfn[3002],low[3002],tot,be[3002],_top,st[3002]; int val1[3002],cnt,hd[3002],nxt[8002],ed[3002],poi[8002]; int val2[3002],cnt2,hd2[3002],nxt2[8002],ed2[3002],poi2[8002]; int in[3002]; bool flag[3002]; inline void add(int x,int y){ nxt[ed[x]]=++cnt; hd[x]= hd[x] ? hd[x]:cnt; ed[x]=cnt; poi[cnt]=y; } inline void add2(int x,int y){ nxt2[ed2[x]]=++cnt2; hd2[x]= hd2[x] ? hd2[x]:cnt2; ed2[x]=cnt2; poi2[cnt2]=y; } inline void tarjan(int x){ dfn[x]=low[x]=++dfs_clock; st[++_top]=x; for(int i=hd[x];i;i=nxt[i]){ if(!dfn[poi[i]]) tarjan(poi[i]),low[x]=min(low[x],low[poi[i]]); else if(!be[poi[i]]) low[x]=min(low[x],dfn[poi[i]]); } if(dfn[x]==low[x]){ be[x]=++tot; val2[tot]=val1[x]; while(st[_top]!=x) be[st[_top]]=tot,val2[tot]=min(val2[tot],val1[st[_top--]]); //维护强连通分量的最小费用 --_top; } } inline void dfs(int x){ flag[x]=1; for(int i=hd2[x];i;i=nxt2[i]) if(!flag[poi2[i]]) dfs(poi2[i]); } int main(){ memset(val1,127,sizeof(val1)); memset(val2,127,sizeof(val2)); read(n); read(m1); int q1,q2; for(int i=1;i<=m1;++i) read(q1),read(q2),val1[q1]=q2; read(m2); for(int i=1;i<=m2;++i) read(q1),read(q2),add(q1,q2); for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;++i) //建新图 for(int j=hd[i];j;j=nxt[j]) if(be[i]!=be[poi[j]]) add2(be[i],be[poi[j]]),++in[be[poi[j]]]; bool ok=1; for(int i=1;i<=tot;++i) if(!in[i]){ //树根 if(val2[i]==val2[0]) ok=0; //没有间谍可收买 ans+=val2[i]; } if(ok) printf("YES\n%d",ans); else{ for(int i=1;i<=tot;++i) if(!in[i]&&val2[i]==val2[0]) dfs(i); //dfs找出所有解决不了的块 for(int i=1;i<=n;++i) if(flag[be[i]]&&val1[i]==val1[0]) {printf("NO\n%d",i); break;} //注意单个间谍也不可以被收买 }return 0; }