洛谷 P1262|P2341|P2002 强连通分量,缩点
来源:互联网 发布:淘宝网店如何装修店铺 编辑:程序博客网 时间:2024/06/05 15:48
图论强连通分量算法,个人感觉tarjan相比两次dfs好写一点(个人看法)
这三道题都在学了强连通分量算法之后都比较基础,貌似都要判断一下缩点之后每个点的入度?
P1262 间谍网络
题意:
直接复制一下数据的输入格式这里,还是比较好理解的吧
第一行只有一个整数n。
第二行是整数p。表示愿意被收买的人数,1≤p≤n。
接下来的p行,每行有两个整数,第一个数是一个愿意被收买的间谍的编号,第二个数表示他将会被收买的数额。这个数额不超过20000。
紧跟着一行只有一个整数r,1≤r≤8000。然后r行,每行两个正整数,表示数对(A, B),A间谍掌握B间谍的证据。
那么对于数对(A,B),我们可以使A指向B建图,之后tarjan算法求强连通分量缩点
tarjan算法退栈的时候,需要判断一下每一个点内部是否都有可以收买的间谍,并且求出内部的点最小的编号
最后处理一下所有的点的入度,检查入度为0的点,如果有一个点的内部没有可以收买的间谍的话直接输出它最小的编号就可以了
代码:
//Decision's template#include<cstdio>#include<cstring>#include<iostream>#include<cstdlib>#include<vector>#include<queue>#include<stack>#include<algorithm>#include<string>#include<cmath>#include<map>#include<set>using namespace std;#define DP_maxn 16#define maxn 100000#define INF 10000007#define mod 1000000007#define mst(s,k) memset(s,k,sizeof(s))typedef long long ll;struct Edge{ int from,to,dist; Edge(int u,int v,int d):from(u),to(v),dist(d){}};/*-------------------------------template End--------------------------------*/int n,need[maxn],p,r,ans = 0,minid[maxn];int First[maxn],Next[maxn],Last[maxn],a[maxn],k = 0;int dfn[maxn],low[maxn],top = 0,q[maxn],fa[maxn],sum = 0,minn[maxn],cnt = 0,s[maxn],in[maxn];bool instack[maxn],flag[maxn];void init(){ mst(First,0); mst(low,0); mst(dfn,0); mst(s,0); mst(in,0); for(int i = 0;i<=3000+10;i++) need[i] = INF,minid[i] = INF,minn[i] = 0;}void add(int x,int y){ k++; a[k] = y; if(First[x]==0) First[x] = k; else Next[Last[x]] = k; Last[x] = k;}void tarjan(int x){ cnt++;top++; low[x] = dfn[x] = cnt; q[top] = x; instack[x] = true; int t = First[x]; while(t!=0) { int v = a[t]; if(dfn[v]==0) { tarjan(v); low[x] = min(low[x],low[v]); } else if(instack[v]) low[x] = min(low[x],dfn[v]); t = Next[t]; } if(dfn[x]==low[x]) { sum++; while(q[top+1] != x) { int tt = q[top]; minid[sum] = min(minid[sum],tt); //cout<<need[tt]<<" "<<need[minn[sum]]<<" "<<need[tt]<<endl; if(need[tt]!=0&&need[minn[sum]]>need[tt]) {minn[sum] = tt;flag[sum] = 1;} //cout<<minn[sum]<<endl; s[sum]++; fa[tt] = sum; instack[tt] = false; top--; } } //cout<<minn[sum]<<endl;}int main(){ //freopen("std.in","r",stdin); //freopen("std.out","w",stdout); init(); cin>>n>>p; for(int i = 1;i<=p;i++) { int id,money; cin>>id>>money; need[id] = money; } cin>>r; for(int i = 1;i<=r;i++) { int tmpx,tmpy; cin>>tmpx>>tmpy; add(tmpx,tmpy); } for(int i = 1;i<=n;i++) { if(dfn[i]==0) tarjan(i); } for(int i = 1;i<=n;i++) { for(int j = First[i];j;j = Next[j]) { int y = a[j]; if(fa[i]!=fa[y]) in[fa[y]]++; } } for(int i = 1;i<=sum;i++) { if(in[i]==0) { if(flag[i]==0) {cout<<"NO"<<endl<<minid[i]<<endl;return 0;} else ans+=need[minn[i]]; } } cout<<"YES"<<endl<<ans<<endl; return 0;}
P2341 [HAOI]受欢迎的牛
N个点M条有向边,给出一点的关系构建一个有向图
求强连通分量,因为在一个强连通分量内部,一个点可以到达其他的所有点,那么也就是说在里面一头牛会认为其他的牛都是受欢迎的,那么可以缩点
缩点之后,遍历一下所有的点,求出缩点之后各点的入度,出度为0的点为所求答案,ans++
代码:
//Decision's template#include<cstdio>#include<cstring>#include<iostream>#include<cstdlib>#include<vector>#include<queue>#include<stack>#include<algorithm>#include<string>#include<cmath>#include<map>#include<set>using namespace std;#define DP_maxn 16#define maxn 100000#define INF 10000007#define mod 1000000007#define mst(s,k) memset(s,k,sizeof(s))typedef long long ll;struct Edge{ int from,to,dist; Edge(int u,int v,int d):from(u),to(v),dist(d){}};/*-------------------------------template End--------------------------------*/int n,m,tmpx,tmpy,top = 0,k = 0,cnt = 0;int First[maxn],Next[maxn],Last[maxn],a[maxn*2],pe[maxn],ppe[maxn];int dfn[maxn],tmp = 0,low[maxn],q[maxn],fa[maxn];bool instack[maxn];void init(){ mst(First,0); mst(Next,0); mst(a,0); mst(dfn,0); mst(low,0);}void add(int x,int y){ k++,a[k] = y; if(First[x]==0) First[x] = k; else Next[Last[x]] = k; Last[x] = k;}void tarjan(int x){ top++;cnt++; dfn[x] = low[x] = cnt; q[top] = x; instack[x] = true; int t = First[x]; while(t!=0){ int v = a[t]; if(dfn[v] == 0){ tarjan(v); if(low[v]<low[x]) low[x] = low[v]; } else if(instack[v]&&dfn[v] < low[x]) low[x] = dfn[v]; t= Next[t]; } if(dfn[x] == low[x]) { n++; while(q[top+1]!=x) { pe[n]++; fa[q[top]] = n; instack[q[top]] = false; top--; } }}int main(){ //freopen("std.in","r",stdin); //freopen("std.out","w",stdout); init(); cin>>n>>m; for(int i = 1;i<=m;i++) { cin>>tmpx>>tmpy; add(tmpx,tmpy); } m = n+1; for(int i = 1;i<=m-1;i++) if(dfn[i]==0) tarjan(i); for(int i = 1;i<=m-1;i++){ for(int o = First[i];o;o = Next[o]) if(fa[i]!=fa[a[o]]) ppe[fa[i]]++; } int pp = 0; for(int i = m;i<=n;i++) if(ppe[i] ==0) pp++; if(pp==1) cout<<pe[m]<<endl; else cout<<"0"<<endl; return 0;}P2002 消息扩散
和上面一题差不多,就是在入度为0的点发布就可以让全部城市都得到消息
//Decision's template#include<cstdio>#include<cstring>#include<iostream>#include<cstdlib>#include<vector>#include<queue>#include<stack>#include<algorithm>#include<string>#include<cmath>#include<map>#include<set>using namespace std;#define DP_maxn 16#define maxn 100000*6#define INF 10000007#define mod 1000000007#define mst(s,k) memset(s,k,sizeof(s))typedef long long ll;struct Edge{ int from,to,dist; Edge(int u,int v,int d):from(u),to(v),dist(d){}};/*-------------------------------template End--------------------------------*/int n,m,tmpx,tmpy,ans = 0;int First[maxn],Next[maxn],Last[maxn],k = 0,ru[maxn];int q[maxn],top = 0,a[maxn],dfn[maxn],low[maxn],cnt = 0,fa[maxn],num[maxn],sum = 0;bool instack[maxn];void add(int x,int y){ k++; a[k] = y; if(First[x]==0) First[x] = k; else Next[Last[x]] = k; Last[x] = k;}void tarjan(int x){ top++;cnt++; dfn[x] = low[x] = cnt; q[top] = x; instack[x] = true; int t = First[x]; while(t!=0) { int v = a[t]; if(dfn[v]==0){ tarjan(v); if(low[v]<low[x]) low[x] = low[v]; } else if(instack[v]&&dfn[v]<low[x]) low[x] = dfn[v]; t = Next[t]; } if(dfn[x]==low[x]) { sum++; while(q[top+1]!=x) { num[sum]++; fa[q[top]] = sum; instack[q[top]] = false; top--; } }}void init(){ mst(dfn,0); mst(low,0); mst(num,0); mst(fa,0);}int main(){ //freopen("std.in","r",stdin); //freopen("std.out","w",stdout); init(); cin>>n>>m; for(int i = 1;i<=m;i++){ cin>>tmpx>>tmpy; add(tmpx,tmpy); } for(int i = 1;i<=n;i++) { if(dfn[i]==0) tarjan(i); } for(int i = 1;i<=n;i++) { for(int j = First[i];j;j = Next[j]) { int v = a[j]; if(fa[i]!=fa[v]) ru[fa[v]]++; } } for(int i = 1;i<=sum;i++) { if(ru[i]==0) ans++; } cout<<ans<<endl; return 0;}
0 0
- 洛谷 P1262|P2341|P2002 强连通分量,缩点
- tarjan强连通分量 洛谷P1262 间谍网络
- 强连通分量缩点
- 强连通分量缩点
- 强连通分量 + 缩点 kosaraju
- 强连通分量缩点的模板
- POJ2186 Tarjan强连通分量+缩点
- 强连通分量+缩点-poj1236
- 强连通分量+缩点uva12167
- poj 2186 强连通分量 缩点
- poj 1236 强连通分量 缩点
- 强连通分量+缩点(poj2553)
- poj1236强连通分量+缩点
- hdu 4635 强连通分量+缩点
- POJ2186Popular Cows(强连通分量+缩点)
- poj 1236 强连通分量+缩点
- poj1236 强连通分量+缩点
- poj2186 强连通分量+缩点
- struts2-Action处理请求参数
- (P2774 方格取数问题)<状压DP>
- 《微习惯》读后感
- struts2-请求参数校验
- 五种开源协议的比较(BSD,Apache,GPL,LGPL,MIT)
- 洛谷 P1262|P2341|P2002 强连通分量,缩点
- JavaWeb数据库开发知识总结(jdbc基础)
- 自己学的排序算法汇总
- POJ2976_Dropping tests_二分最大化平均值
- Linux上搭建tomcat
- JAVA 构造器+布局分析
- Flok_Fulkerson算法
- jQuery之Deferred对象的使用
- qmake使用