loj10095 间谍网络
題目描述
由于外國間諜的大量滲入,國家安全正處于高度危機之中。如果A間諜手中掌握著關于B間諜的犯罪證據,則稱A可以揭發B。有些間諜接受賄賂,只要給他們一定數量的美元,他們就愿意交出手中掌握的全部情報。所以,如果我們能夠收買一些間諜的話,我們就可能控制間諜網中的每一分子。因為一旦我們逮捕了一個間諜,他手中掌握的情報都將歸我們所有,這樣就有可能逮捕新的間諜,掌握新的情報。
我們的反間諜機關提供了一份資料,包括所有已知的受賄的間諜,以及他們愿意收受的具體數額。同時我們還知道哪些間諜手中具體掌握了哪些間諜的資料。假設總共有n個間諜,每個間諜分別用1到n的整數來標識。
請根據這份資料,判斷我們是否可能控制全部的間諜,如果可以,求出我們所需要支付的最少資金。否則,輸出不能被控制的一個間諜。
輸入格式
第一行只有一個整數n。第二行是整數p。表示愿意被收買的人數。
接下來的p行,每行有兩個整數,第一個數是一個愿意被收買的間諜的編號,第二個數表示他將會被收買的數額。
緊跟著一行只有一個整數r。然后r行,每行兩個正整數,表示數對(A,B) ,A間諜掌握B間諜的證據。
輸出格式
如果可以控制所有間諜,第一行輸出YES,并在第二行輸出所需要支付的賄金最小值。否則輸出NO,并在第二行輸出不能控制的間諜中,編號最小的間諜編號。
樣例
樣例輸入
2
1
2 512
2
1 2
2 1
樣例輸出
YES
512
數據范圍與提示
1<=n<=3000,1<=p<=n,1<=r<=8000,每個收買的費用為非負數且不超過20000。
------------------------------------------------------------------------------------------------------------------
首先,將各個強連通分量進行縮點,建立新圖,求出第一分量的入度。
然后,并記錄每一個分量中的最小點編號和分量內點中能買通的最少花費。
第三,把每一個分量標明是否可以被買通,入度為0的分量的最小花費和就是整個圖的最少花費和。
第四步,拓撲排序,把所有可以買通的點的后續點都設為可以買通。
第五步,所有不可買通的分量中編號最小的點的編號就是不可買通的最小編號。
最后,通過最小編號是否求出可以判斷是否可以全部買通。從而輸出相應的內容。
------------------------------------------------------------------------------------------------------------------
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=3010; 4 const int maxm=8010; 5 int n,m,p; 6 struct edge 7 { 8 int u,v,nxt; 9 }e[maxm]; 10 int head[maxn],js; 11 void addage(int u,int v) 12 { 13 e[++js].u=u;e[js].v=v; 14 e[js].nxt=head[u];head[u]=js; 15 } 16 int sm[maxn][2]; 17 int dfn[maxn],low[maxn],st[maxn],top,cnt,lt[maxn],lts; 18 void tarjan(int u) 19 { 20 dfn[u]=low[u]=++cnt; 21 st[++top]=u; 22 for(int i=head[u];i;i=e[i].nxt) 23 { 24 int v=e[i].v; 25 if(!dfn[v]) 26 { 27 tarjan(v); 28 low[u]=min(low[u],low[v]); 29 } 30 else if(!lt[v]) 31 low[u]=min(low[u],dfn[v]); 32 } 33 if(low[u]==dfn[u]) 34 { 35 lt[u]=++lts; 36 while(st[top]!=u)lt[st[top--]]=lts; 37 --top; 38 } 39 } 40 int rd[maxn],msm[maxn]; 41 edge ee[maxm]; 42 int headd[maxn],jss; 43 void addagee(int u,int v) 44 { 45 ee[++jss].u=u;ee[jss].v=v; 46 ee[jss].nxt=headd[u];headd[u]=jss; 47 } 48 queue<int>q; 49 bool ksm[maxn]; 50 int mno[maxn]; 51 int ans,mbk=0x7f7f7f7f; 52 int main() 53 { 54 scanf("%d%d",&n,&p); 55 for(int i=1;i<=p;++i) 56 scanf("%d%d",&sm[i][0],&sm[i][1]); 57 scanf("%d",&m); 58 for(int u,v,i=0;i<m;++i) 59 { 60 scanf("%d%d",&u,&v); 61 addage(u,v); 62 } 63 for(int i=1;i<=n;++i) 64 if(!dfn[i])tarjan(i); 65 for(int i=1;i<=n;++i) 66 for(int j=head[i];j;j=e[j].nxt) 67 { 68 if(lt[i]!=lt[e[j].v]) 69 { 70 rd[lt[e[j].v]]++; 71 addagee(lt[i],lt[e[j].v]); 72 } 73 } 74 memset(msm,0x7f,sizeof msm); 75 memset(mno,0x7f,sizeof mno); 76 for(int i=1;i<=p;++i) 77 if(msm[lt[sm[i][0]]]>sm[i][1])msm[lt[sm[i][0]]]=sm[i][1],ksm[lt[sm[i][0]]]=1; 78 for(int i=1;i<=n;++i) 79 if(i<mno[lt[i]])mno[lt[i]]=i; 80 for(int i=1;i<=lts;++i) 81 if(rd[i]==0)q.push(i),ans+=msm[i]; 82 while(!q.empty()) 83 { 84 int u=q.front();q.pop(); 85 for(int i=headd[u];i;i=ee[i].nxt) 86 { 87 int v=ee[i].v; 88 rd[v]--; 89 if(ksm[u])ksm[v]=1; 90 if(rd[v]==0)q.push(v); 91 } 92 } 93 for(int i=1;i<=lts;++i) 94 { 95 if(!ksm[i])mbk=min(mbk,mno[i]); 96 } 97 if(mbk==0x7f7f7f7f)printf("YES\n%d",ans); 98 else printf("NO\n%d",mbk); 99 return 0; 100 } View Code?
轉載于:https://www.cnblogs.com/gryzy/p/10763029.html
總結
以上是生活随笔為你收集整理的loj10095 间谍网络的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 词典增加和删除
- 下一篇: 英国诺丁汉大学读研费用一年多少