Information Graph CodeForces - 466E
2017-05-08 10:13
211 查看
There are n employees working in company “X” (let’s number them from 1 to n for convenience). Initially the employees didn’t have any relationships among each other. On each of m next days one of the following events took place:
either employee y became the boss of employee x (at that, employee x didn’t have a boss before);
or employee x gets a packet of documents and signs them; then he gives the packet to his boss. The boss signs the documents and gives them to his boss and so on (the last person to sign the documents sends them to the archive);
or comes a request of type “determine whether employee x signs certain documents”.
Your task is to write a program that will, given the events, answer the queries of the described type. At that, it is guaranteed that throughout the whole working time the company didn’t have cyclic dependencies.
Input
The first line contains two integers n and m (1 ≤ n, m ≤ 105) — the number of employees and the number of events.
Each of the next m lines contains the description of one event (the events are given in the chronological order). The first number of the line determines the type of event t (1 ≤ t ≤ 3).
If t = 1, then next follow two integers x and y (1 ≤ x, y ≤ n) — numbers of the company employees. It is guaranteed that employee x doesn’t have the boss currently.
If t = 2, then next follow integer x (1 ≤ x ≤ n) — the number of the employee who got a document packet.
If t = 3, then next follow two integers x and i (1 ≤ x ≤ n; 1 ≤ i ≤ [number of packets that have already been given]) — the employee and the number of the document packet for which you need to find out information. The document packets are numbered started from 1 in the chronological order.
It is guaranteed that the input has at least one query of the third type.
Output
For each query of the third type print “YES” if the employee signed the document package and “NO” otherwise. Print all the words without the quotes.
Example
Input
4 9
1 4 3
2 4
3 3 1
1 2 3
2 2
3 1 2
1 3 1
2 2
3 1 3
Output
YES
NO
YES
/*
either employee y became the boss of employee x (at that, employee x didn’t have a boss before);
or employee x gets a packet of documents and signs them; then he gives the packet to his boss. The boss signs the documents and gives them to his boss and so on (the last person to sign the documents sends them to the archive);
or comes a request of type “determine whether employee x signs certain documents”.
Your task is to write a program that will, given the events, answer the queries of the described type. At that, it is guaranteed that throughout the whole working time the company didn’t have cyclic dependencies.
Input
The first line contains two integers n and m (1 ≤ n, m ≤ 105) — the number of employees and the number of events.
Each of the next m lines contains the description of one event (the events are given in the chronological order). The first number of the line determines the type of event t (1 ≤ t ≤ 3).
If t = 1, then next follow two integers x and y (1 ≤ x, y ≤ n) — numbers of the company employees. It is guaranteed that employee x doesn’t have the boss currently.
If t = 2, then next follow integer x (1 ≤ x ≤ n) — the number of the employee who got a document packet.
If t = 3, then next follow two integers x and i (1 ≤ x ≤ n; 1 ≤ i ≤ [number of packets that have already been given]) — the employee and the number of the document packet for which you need to find out information. The document packets are numbered started from 1 in the chronological order.
It is guaranteed that the input has at least one query of the third type.
Output
For each query of the third type print “YES” if the employee signed the document package and “NO” otherwise. Print all the words without the quotes.
Example
Input
4 9
1 4 3
2 4
3 3 1
1 2 3
2 2
3 1 2
1 3 1
2 2
3 1 3
Output
YES
NO
YES
/*
`` 题意:好复杂2333嗯。。自己看看吧大概也看得懂。。。2333(其实是我忘记了=-=) 思路:对同一个文件的查询,查询的关系树应该是2操作时的关系树,所以对每个2操作 我们可以把所有的对当时文件的查询一起处理。这里学到了个很厉害的东西。用dfs标记一个点入栈退栈的时间,用一个时间戳Index来计算,那么如果有一对点u,v,v在u到根节点的路径上,即r->v->u;那么必定存在 l[v]<l[u] r[v]>r[u]。由于1操作对关系图中的时间戳不会产生影响,并且需要将对同一文件的查询一起处理,所以我们先把所有操作读入,然后一起操作。2333 对每个1操作,我们用并查集合并x,y,然后先将所有3操作根据文件标号存好,对每个2操作去查询得到当前文件的人和被查询的人是不是同属一个集合,如果属于一个集合说明已经被合并如果同时满足lr的关系那么说明yes 不然no2333*/
#include<iostream> #include<algorithm> #include<vector> #include<queue> #include<vector> #include<cmath> #include<cstdio> #include<cstring> #include<string> #include<stack> #include<map> using namespace std; //thanks to pyf ... #define INF 0x3f3f3f3f #define CLR(x,y) memset(x,y,sizeof(x)) #define mp(x,y) make_pair(x,y) typedef pair<int,int> PII; typedef long long ll; const int N = 1e5+5; int fa ; vector<int>G ;//存图 vector<PII>Q ;//用来存放查询 first是查询的人 second是查询的编号 int l ,r ;//入退栈的时间 int ok ;//yes or no int vis ;//用来标记是否有入度,没入度的是根节点 int Index = 0;//时间戳 int doc_id = 0;//文件标号 int n,m; struct Q { int op; int x,y; }query ; void init()//初始化函数 { CLR(ok,0); CLR(vis,0); CLR(l,0); CLR(r,0); Index = 0; doc_id = 0; for(int i=0;i<=N;i++) { fa[i] = i; G[i].clear(); Q[i].clear(); } } int find(int x) { if(fa[x]!=x) fa[x] = find(fa[x]); return fa[x]; } void merge(int a,int b) { a = find(a); b = find(b); if(a!=b) fa[a] = fa[b]; } void get_query()//预处理所有操作 { scanf("%d",&m); for(int i=0;i<m;i++) { int op; scanf("%d",&query[i].op); if(query[i].op==1) //反向建图,这样由最高领导指向所有下属,在dfs时对根节点不会重复的去覆盖lr值 { scanf("%d%d",&query[i].x,&query[i].y); G[query[i].y].push_back(query[i].x); vis[query[i].x] = 1; // 有入度 不是根节点 } else if(query[i].op == 2) { scanf("%d",&query[i].x); query[i].y = ++ doc_id; } else { scanf("%d%d",&query[i].x,&query[i].y); Q[query[i].y].push_back(mp(query[i].x,i)); //对同一个文件的查询存放在一起 } } } void dfs(int u)//处理 lr { vis[u] = 1; l[u] = ++ Index; for(int i=0;i<G[u].size();i++) { int v = G[u][i]; dfs(v); } r[u] = ++Index; } int main() { while(scanf("%d",&n)==1) { init(); get_query(); for(int i=1;i<=n;i++) if(!vis[i]) dfs(i); for(int i=0;i<m;i++) { if(query[i].op == 1) { merge(query[i].x,query[i].y); } else if(query[i].op==2) { int get_p = query[i].x; int doc = query[i].y; for(int j=0;j<Q[doc].size();j++) //判断是否可行 { int p = Q[doc][j].first; int id = Q[doc][j].second; // cout << get_p << " " << p << " "; // cout << l[get_p] << " " << l[p] << " " << r[get_p] << " " << r[p] << " " << find(get_p) << " " << find(p) << endl; if(l[get_p]>=l[p]&&r[get_p]<=r[p]&&(find(get_p)==find(p))) ok[id] = 1; } } } for(int i=0;i<m;i++) if(query[i].op == 3) ok[i]==1 ? cout << "YES" << endl : cout << "NO" << endl; } return 0; }
相关文章推荐
- [博弈论] Codeforces Gym 101190 NEERC 16 G. Game on Graph
- Educational Codeforces Round 2 Edge coloring of bipartite graph
- Codeforces Round #286 (Div. 1) D. Mr. Kitayuta's Colorful Graph 高维并查集,STL连招
- Dima and Trap Graph CodeForces - 366D 并查集
- codeforces#236_div2_C Searching for Graph
- Educational Codeforces Round 36 (Rated for Div. 2)D. Almost Acyclic Graph(正解!!百度的那些拓扑排序现在都已经TLE!)
- 状态压缩DP joboj1430 shortest path 和 codeforces Problem 21 D Traveling Graph
- C - Restore Graph CodeForces - 404C BFS+小trick
- Codeforces Gym 101190 NEERC 16 G. Game on Graph(博弈+拓扑)
- codeforces#236_div2_C Searching for Graph
- Round 6 B - Greg and Graph CodeForces - 295Div.1B - Floyd && DP
- codeforces Round 36 D. Almost Acyclic Graph(dfs+拓扑排序判环)
- codeforces Dima and Trap Graph
- C - Colorful Graph CodeForces - 246D (暴力坑题)
- 【Educational Codeforces Round 36 D】 Almost Acyclic Graph
- [Codeforces VK Cup 2016 - Round 2][矩阵树定理][高斯消元][骗(满)分]G. Little Artem and Graph
- codeforces Searching for Graph
- Educational Codeforces Round 15 E. Analysis of Pathes in Functional Graph (倍增法)
- Educational Codeforces Round 15 Analysis of Pathes in Functional Graph rmq 变形
- Codeforces C Graph and String