1298. 通讯问题
★ 输入文件:jdltt.in
输出文件:jdltt.out
简单对比
时间限制:1 s 内存限制:128 MB
【题目描述】
一个篮球队有n个篮球队员,每个队员都有联系方式(如电话、电子邮件等)。但并不是每个队员的联系方式都公开,每个队员的联系方式只有一部分队员知道。问队员可以分成多少个小组,小组成员之间可以相互通知(包括一个队员一个组,表示自己通知自己)。
【输入格式】
输入文件有若干行
第一行,一个整数n,表示共有n个队员(2<=n<=100)
下面有若干行,每行2个数a、b,a、b是队员编号,表示a知道b的通讯方式。
【输出格式】
输出文件有若干行
第一行,1个整数m,表示可以分m个小组,下面有m行,每行有若干个整数,表示该小组成员编号,输出顺序按编号由小到大。
【样例输入】
- 12
- 1 3
- 2 1
- 2 4
- 3 2
- 3 4
- 3 5
- 4 6
- 5 4
- 6 4
- 7 4
- 7 8
- 7 12
- 8 7
- 8 9
- 10 9
- 11 10
【样例输出】
8
1 2 3
4 6
5
7 8
9
10
11
12
暴力代码
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; int n,m,k,x,y; #define N 110 int a[N][N],b[N/2][N],vis[N],jl[N],zj=0,tot=0,t1=0,qi; void bj(int z){ for(int i=0;i<zj;i++) vis[jl[i]]=1; sort(jl,jl+zj); zj=unique(jl,jl+zj)-jl; for(int i=0;i<zj;i++) b[jl[0]][i]=jl[i]; tot++; for(int i=0;i<zj;i++) jl[i]=0; zj=0; } void dfs(int u,int v){ if(vis[u]||vis[v]||u==v) return; if(v==qi) {bj(zj); return;} if(a[u][v]&&!vis[v]) { jl[zj++]=v; for(int j=1;j<=n;j++){ if(a[v][j]&&!vis[j]) dfs(v,j); } } if(u==qi&&zj>0) zj--; } int main() { freopen("jdltt.in","r",stdin); freopen("jdltt.out","w",stdout); scanf("%d",&n); while(scanf("%d%d",&x,&y)==2){ a[x][y]=1; } for(qi=1;qi<=n;qi++){ for(int j=1;j<=n;j++) if(qi!=j&&a[qi][j]){ if(!vis[qi]){ if(!vis[j]){ jl[zj++]=qi; dfs(qi,j); }else continue; }else break; } } for(int i=1;i<=n;i++) if(!vis[i]) t1++; printf("%d ",t1+tot); for(int i=1;i<=n;i++){ if(b[i][0]!=0){ for(int j=0;b[i][j];j++){ printf("%d ",b[i][j]); } printf(" "); } else if(!vis[i]) printf("%d ",i); } return 0; }
暴力代码虽然ac(数据太水),但有bug;
例如
输入数据 5 1 2 2 3 3 1 2 4 4 5 5 1 正确输出 1 1 2 3 4 5
然而 不对;
正确tarjan算法:(一样ac)
#include<cstdio> #include<iostream> #include<vector> #include<stack> #include<algorithm> #define M 100010 #define N 2010 using namespace std; vector<int> grap[M]; stack<int> s; int low[M],num[M],vis[M],instack[M]; int index,cnt,n; struct node{ int sum; int dl[N]; void px() { sort(dl+1,dl+sum+1); } };node f[N]; int cmp(const node&x,const node&y) { return x.dl[1]<y.dl[1]; } void tarjan(int v) { low[v]=num[v]=++index; s.push(v); instack[v]=1; vis[v]=1; for(int i=0;i<grap[v].size();i++){ int w=grap[v][i]; if(!vis[w]){ tarjan(w); low[v]=min(low[v],low[w]); } else if(instack[w]) low[v]=min(low[v],num[w]); } int u; if(low[v]==num[v]){ ++cnt; do { u=s.top(); f[cnt].dl[++f[cnt].sum]=u; s.pop(); instack[u]=0; }while(u!=v); } } int main() { freopen("jdltt.in","r",stdin); freopen("jdltt.out","w",stdout); int x,y; scanf("%d",&n); while(scanf("%d%d",&x,&y)==2) grap[x].push_back(y); for(int i=1;i<=n;i++) if(!vis[i])tarjan(i); printf("%d ",cnt); for(int i=1;i<=cnt;i++) f[i].px(); sort(f+1,f+cnt+1,cmp); for(int i=1;i<=cnt;i++){ for(int j=1;j<=f[i].sum;j++) printf("%d ",f[i].dl[j]); printf(" "); } return 0; }