1. Is It A Tree?-树,并查集
-
题意
给定多条有向边的图,问这个图是不是一个树
-
思路
有两种思路
-
一种是用邻接表构建这个图,然后以入度为 0 的点为根,遍历这个图
如果入度为 0 的点有多个,或者在遍历的时候访问到了已经访问过的点,则不是一棵树
-
另一种思路就是用并查集
如果合并的时候两个点已经在同一个集合中了,或者最终根节点的个数多于 1 ,则不是一棵树
// 思路1 int cnt = 1; bool stop; map<int, vector<int> > tree; map<int, int> indgree; void solve(){int u, v;map<int, vector<int> > ctree;map<int, int> cindgree;swap(tree, ctree), swap(indgree, cindgree);int ccc = 0;while(cin >> u >> v){if(u==0 && v==0) break;if(u==-1 && v==-1){stop = true;return;}ccc++;tree[u].push_back(v);indgree[u] = indgree[u];indgree[v]++;}if(ccc == 0){cout << "Case " << cnt++ << " is a tree." << endl;return;}int cc = 0, sta = -1;for(map<int, int>::iterator x=indgree.begin(); x!=indgree.end(); x++){if(x->second == 0){cc++;sta = x->first;}}if(sta == -1 || cc > 1){cout << "Case " << cnt++ << " is not a tree." << endl;return;}map<int, bool> vis;queue<int> q;q.push(sta);while(!q.empty()){int now = q.front(); q.pop();if(vis[now]){cout << "Case " << cnt++ << " is not a tree." << endl;return;}vis[now] = true;vector<int> c;swap(c, tree[now]);int len = c.size();for(int i=0; i<len; i++){int next = c[i];if(vis[next]){cout << "Case " << cnt++ << " is not a tree." << endl;return;}q.push(next);}}cout << "Case " << cnt++ << " is a tree." << endl; } signed main(){io;Test;int t; t = 1;while(t){solve();if(stop) break;} }
// 思路2, 这个算法的所用的时间明显少于思路1 int cnt = 1; bool stop; map<int, int> pre; int find(int now){if(pre[now] == now) return now;return pre[now] = find(pre[now]); } void solve(){int u, v, t = true;;map<int, int> cpre; swap(cpre, pre);int cc = 0;while(cin >> u >> v){if(u==0 && v==0) break;if(u==-1 && v==-1){stop = true;return;}cc++;if(t == false) continue;if(pre[u] == 0) pre[u] = u;if(pre[v] == 0) pre[v] = v;int ru = find(u), rv = find(v);if(ru == rv){t = false;continue;}pre[ru] = rv;}map<int, int>::iterator pos;map<int, bool> vis;for(pos=pre.begin(); pos!=pre.end(); pos++){vis[find(pos->first)] = true; // 这里是并查集中判断是否在一个集合中的公式,很多时候都会用到}int len = vis.size();if(len > 1){t = false;}if(cc == 0) t = true;if(t) cout << "Case " << cnt++ << " is a tree.";else cout << "Case " << cnt++ << " is not a tree.";cout << endl; } signed main(){io;Test;int t; t = 1;// cin >> t;while(t){solve();if(stop) break;} }
-
-
总结
题目不难,就是简单的并查集