Time Limit: 2000MS | Memory Limit: 10000K | |
Total Submissions: 18141 | Accepted: 5807 |
Description
Input
Output
Sample Input
5 5:(3) 1 4 2 1:(0) 4:(0) 2:(1) 3 3:(0) 6 (1 5) (1 4) (4 2) (2 3) (1 3) (4 3)
Sample Output
2:1 5:5
#include"stdio.h" #include"iostream" #include"algorithm" #include"string.h" #include"vector" using namespace std; const int maxn = 1000+10; struct node ///邻接表 { int to; int next; }e[maxn]; int n,m; int top; ///邻接表边的条数 int ans[maxn]; ///次数 int head[maxn]; ///邻接表头结点 int fa[maxn]; ///并查集的父亲结点 int in[maxn]; ///定点入度,用来寻找根节点 int vis[maxn]; ///Tarjan里面进行标记 int flag[maxn][maxn]; ///一个询问可能出现多次,正向或者反向的询问都只能加一次,所以需要标记 int query[maxn][maxn];///询问次数 void INIT() ///初始化 { top = 0; for(int i = 0;i < maxn;i++) { ans[i] = vis[i] = in[i] = 0; head[i] = -1; fa[i] = i; } memset(query,0,sizeof query); memset(flag,0,sizeof flag); } void add(int u,int v) ///邻接表加边 { e[top].to = v; e[top].next = head[u]; head[u] = top++; } int Find(int x) { if(x != fa[x]) fa[x] = Find(fa[x]); return fa[x]; } void Union(int x,int y) ///并查集联合 { int fx = Find(x); int fy = Find(y); fa[fy] = fx; } void Tarjan(int u) { vis[u] = 1; for(int i = head[u];i != -1;i = e[i].next) { int t = e[i].to; Tarjan(t); Union(u,t); } for(int i = 1;i <= n;i++) { if(vis[i] && query[u][i] && !flag[u][i]) ans[Find(i)] += query[u][i],flag[u][i] = flag[i][u] = 1; ///双向加标记,一种询问只能加一次 } } int main(void) { while(scanf("%d",&n) != EOF) { INIT(); for(int i = 1;i <= n;i++) { int h,sons; scanf("%d:(%d)",&h,&sons); for(int j = 1;j <= sons;j++) { int son; scanf("%d",&son); add(h,son); in[son]++; } } scanf("%d",&m); for(int i = 1;i <= m;i++) { int a,b; scanf(" (%d %d)",&a,&b); query[a][b]++; query[b][a]++; ///双向加 } for(int i = 1;i <= n;i++) if(in[i] == 0) Tarjan(i); for(int i = 1;i <= n;i++) { if(ans[i]) { printf("%d:%d\n",i,ans[i]); } } } return 0; }