Once upon a time, human have not invented boats and planes, bridges were the most important things in communication among islands. There is a large kingdom consists of N islands. One day, a terrible war broken out in this country. Due to the war, there might be several bridges being built or destroyed in each day. Tom, one of your best friends, is a business man. People always earn lots of money during the war, and certainly Tom doesn't want to lose this chance. But he doesn't know whether he can get to one island from another island, so he comes to you for help.
Input
There are multiple cases. The first line of each case consists of two integers N and M (1≤N≤500, 1≤M≤50000), indicates the number of islands and the number of operations. The indies of the island are from 1 to N. Then comes M lines of operations. There are three kinds of operations:
- I x y: means they build a bridge connects island x and island y
- D x y: means they destroy the bridge which connects island x and island y
- Q x y: Tom want to know whether he can get to island y from island x
Assume there are no bridges at the beginning, and each bridge will be built at most once(means when one bridge is destroyed, you can never build it any more)
Output
In the first line, you must output the case number. And for each query, you must output "YES" if you can get to island y from island x. otherwise output "NO".
Print a blank line between cases.
Sample Input
5 9 I 1 2 I 2 3 Q 1 3 I 1 3 I 2 4 I 4 5 D 1 2 D 2 3 Q 1 5
Sample Output
Case 1: YES NO
Author: YANG, Kete
看别人的.
50000次操作, 所以普通做法会超时.
每个边最多删除一次, 插入一次, 可以在插入边的时候同时删除边, 同时只要保证连通性就行了, 当要加入边a, b时, 假设在加边前 a 和 b 之间只有一条路, 组成这条路的边在以后某个时刻会被删掉, 让我们删掉将最早被删除的边, 再加入ab边, 这样保证了连通性, 也保证了边数尽量少, 也符合前面的假设(ab间只有一条路). 其实每个连同分量是一棵树, 边保持在O(n), 那么对图的每次遍历相当于对树的遍历, 这样就有O(n*m)的复杂度.
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <algorithm>
#include <vector>
#include <utility>
using namespace std;
#define NODES_MAX 510
#define INPUTS_MAX 50010
#define INF 100000000
vector <vector <int> > adj;
bool isEdge [NODES_MAX][NODES_MAX];
int deleteTime [NODES_MAX][NODES_MAX];
struct Input {
char _op;
int _a, _b;
Input (char op, int a, int b): _op (op), _a (a), _b (b) {}
Input (const Input &i): _op (i._op), _a (i._a), _b (i._b) {}
};
vector <Input> input;
void InitGraph (int n) {
adj.clear();
adj.resize (n);
memset (isEdge, 0, sizeof (isEdge));
}
void NewEdge (int a, int b) {
if (isEdge [a][b]) {
return;
}
adj[a].push_back (b);
adj[b].push_back (a);
isEdge [a][b] = isEdge [b][a] = true;
#ifdef _DEBUG
printf ("new edge (%d====%d)\n", a, b);
#endif
}
void DeleteEdge (int a, int b) {
if (! isEdge [a][b]) {
return;
}
int i = int (find (adj[a].begin(), adj[a].end(), b) - adj[a].begin());
swap (adj[a][i], (int &) (adj[a].back()));
adj[a].pop_back();
i = int (find (adj[b].begin(), adj[b].end(), a) - adj[b].begin());
swap (adj[b][i], (int &) (adj[b].back()));
adj[b].pop_back();
isEdge [a][b] = isEdge [b][a] = false;
#ifdef _DEBUG
printf ("delete edge (%d====%d)\n", a, b);
#endif
}
bool DFS (int v, int dest, int father, int &ind) {
if (v == dest) {
return true;
}
// try every edge 'v' ====> 'a'
for (int i=0; i<int(adj[v].size()); ++i) {
int a = adj[v][i];
if (a != father && DFS (a, dest, v, ind)) {
ind = min (ind, deleteTime [v][a]);
return true;
}
}
return false;
}
int main () {
int n, m;
while (scanf ("%d%d", &n, &m) == 2) {
InitGraph (n);
input.clear();
fill (deleteTime[0], deleteTime[NODES_MAX], INF);
for (int i=0; i<m; ++i) {
int a, b;
char op[2];
scanf ("%s%d%d", op, &a, &b);
--a, --b;
input.push_back (Input (*op, a, b));
if (*op == 'D') {
deleteTime [a][b] = deleteTime [b][a] = i;
}
}
static int cs = 0;
printf (cs ? "\n" : "");
printf ("Case %d:\n", ++cs);
for (int i=0; i<int(input.size()); ++i) {
if (input[i]._op == 'D') {
DeleteEdge (input[i]._a, input[i]._b);
} else if (input[i]._op == 'Q') {
int t = INF;
printf (DFS (input[i]._a, input[i]._b, -1, t) ? "YES\n" : "NO\n");
} else {
int t = INF;
if (! DFS (input[i]._a, input[i]._b, -1, t)) {
NewEdge (input[i]._a, input[i]._b);
} else if (t < INF) {
DeleteEdge (input[t]._a, input[t]._b);
NewEdge (input[i]._a, input[i]._b);
}
}
}
}
return 0;
}