Poj2838 Graph Connectivity
Graph Connectivity
Time Limit:8000 MS |
|
Memory Limit:131072 K |
Total Submissions:3381 |
|
Accepted:883 |
Case Time Limit:3000 MS |
Description
Let us consider
UndirectedGraph G = <V, E>. at first there is no edge in the graph. you are to write a program to calculate the connectivity of two different vertices. your program shocould maintain the functions inserting or deleting an edge.
Input
The first line of the input contains an integer numbers N (2 <=n <= 1000) -- the number of vertices in G. the second line contains the number of commands Q (1 <= Q <= 20000 ). then the following Q lines describe each command, and there are three kinds of commands:
I u v: Insert an edge (u, v). And we guarantee that there is no edge between nodes u and v, when you face this command.
D u v: Delete an existed edge (u, v). And we guarantee that there is an edge between nodes u and v, when you face this command.
Q u v: A querying command to ask the connectivity between nodes u and v.
You shoshould notice that the nodes are numbered from 1 to N.
Output
Output one line for each querying command. Print "Y" if two vertices are connected or print "N" otherwise.
Sample Input
3 7Q 1 2I 1 2I 2 3Q 1 3D 1 2Q 1 3Q 1 1
Sample Output
NYN
Y
The question is: given the number of points, giving an undirected edge, you can dynamically Add a delete query to check whether two points are connected.
Solution 1
It is easy to think of graphs here. Create an adjacent table and directly use bfs for queries. Of course, dfs is similar. Here we provide bfs queries and the adjacent table, so we can use vector for calculation. We can be very lazy!
#include "stdio.h"#include "string.h"#include "math.h"#include #include
#include
#include
using namespace std;#define M 1000000#define N 20005vector
edge[N];bool vis[N];queue
que;bool query(int s, int e){if (s == e)return true;memset(vis, false, sizeof(vis));vis[s] = true;while (!que.empty()){que.pop();}que.push(s);while (!que.empty()){int k = que.front();que.pop();vector
::iterator it;for (it = edge[k].begin(); it != edge[k].end(); it++){if (*it == e)return true;if (!vis[*it]){que.push(*it);vis[*it] = true;}}}return false;}void inset(int s, int e){edge[s].push_back(e);}void deleteedge(int s, int e){vector
::iterator it;int i;for (it = edge[s].begin(), i = 0; it != edge[s].end(); it++, i++){if (*it == e){edge[s].erase(it);return;}}}void init(){for (int i = 0; i < N; i++){edge[i].clear();}}int main(){int n, tcase;char q;int s, e;while (scanf("%d", &tcase) != EOF){init();scanf("%d", &n);while (n--){getchar();q = getchar();scanf("%d%d", &s, &e);//printf("%c %d %d", q, s, e);if (q == 'Q'){if (query(s, e))printf("Y\n");elseprintf("N\n");}else if (q == 'I'){inset(s, e);inset(e, s);}else if (q == 'D'){deleteedge(s, e);deleteedge(e, s);}}}return 0;}
The second solution is to use and check the set and add the hash table. Here there are 1000 points, so we can use the hash table. I don't want to apply it if it is a little bigger. Use and query the set. Indeed, yes, fast Query
Whether the two points are connected, but if they are deleted, they will undoubtedly re-build and query the set. This is very time-consuming. Check the source code.
#include "stdio.h"#include "string.h"#include "math.h"#include #include
using namespace std;#define N 1005#define M 20005bool edge[N][N];int father[N];void initFather();int insertFather(int s, int e);int findfather(int s);int ncount;struct node {int s, e;};node queue[M];int sum = 0;void createFather(){initFather();for (int i = 0; i < sum;i++){if (edge[queue[i].s][queue[i].e])insertFather(queue[i].s, queue[i].e);}}void initFather(){for (int i = 0; i <= ncount; i++){father[i] = i;}}int insertFather(int s, int e){int x = findfather(s);int y = findfather(e);if ( x != y)father[x] = findfather(y);return 0;}int findfather(int s){if (father[s] == s)return s;elsereturn father[s] = findfather(father[s]);}bool query(int s, int e){if (findfather(s) == findfather(e))return true;else return false;}void deleteedge(int s, int e){edge[s][e] = false;}void init(){memset(edge, false, sizeof(edge));sum = 0;createFather();}int main(){int n,tcase;char q;int s, e;while (scanf_s("%d", &tcase) != EOF){//while (tcase--){ncount = tcase;init();scanf_s("%d", &n);while (n--){getchar();q = getchar();scanf_s("%d%d", &s, &e);//printf("%c %d %d", q, s, e);if (q == 'Q'){if (query(s, e))printf("Y\n");elseprintf("N\n");}else if (q == 'I'){edge[s][e] = true;edge[e][s] = true;queue[sum].s = s;queue[sum].e = e;sum++;insertFather(s, e);}else if (q == 'D'){deleteedge(s, e);deleteedge(e, s);createFather();}}}}return 0;}
The third method adds and queries the set in the adjacent table, which saves time and memory compared with the preceding two methods.
#include "stdio.h"#include "string.h"#include "math.h"#include #include
#include
#include
using namespace std;#define N 1005#define SCANF scanfvector
edge[N];int ncount;queue
que;int father[N];void initFather();int insertFather(int s, int e);int findfather(int s);void createFather(){initFather();int i = 0;vector
::iterator it;for (int s = 0; s <= ncount; s++){for (it = edge[s].begin(), i = 0; it != edge[s].end(); it++, i++){insertFather(s, *it);}}}void initFather(){for (int i = 0; i <= ncount; i++){father[i] = i;}}int insertFather(int s, int e){int x = findfather(s);int y = findfather(e);if (x != y)father[x] = findfather(y);return 0;}int findfather(int s){if (father[s] == s)return s;elsereturn father[s] = findfather(father[s]);}bool query(int s, int e){if (findfather(s) == findfather(e))return true;elsereturn false;}void inset(int s, int e){edge[s].push_back(e);insertFather(s, e);}void deleteedge(int s, int e){vector
::iterator it;int i;for (it = edge[s].begin(), i = 0; it != edge[s].end(); it++, i++){if (*it == e){edge[s].erase(it);return;}}}void init(){for (int i = 0; i <= ncount; i++){edge[i].clear();}createFather();}int main(){int n, tcase;char q;int s, e;while (SCANF("%d", &tcase) != EOF){ncount = tcase;init();SCANF("%d", &n);while (n--){getchar();q = getchar();SCANF("%d%d", &s, &e);//printf("%c %d %d", q, s, e);if (q == 'Q'){if (query(s, e))printf("Y\n");elseprintf("N\n");}else if (q == 'I'){inset(s, e);inset(e, s);}else if (q == 'D'){deleteedge(s, e);deleteedge(e, s);createFather();}}}return 0;}