题目
题解1
挺水的题, 枚举割点在判断S->T是否联通即可
CODE1
但下面的代码无疑会超时
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 100;
typedef long long ull;
typedef pair <int, int > pii;
inline int read() {
int s = 0, w = 1;
char ch = getchar();
while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }
while (isdigit(ch)) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
return s * w;
}
const int inf = 0x3f3f3f3f;
int n, a, b;
struct Edge { int next, to; } edge[maxn];
int num_edge = 0, tim = 0, ss = 0, s, e;
int head[maxn], low[maxn], dfn[maxn], cnt[maxn], vis[maxn];
int t[maxn], point = inf;
bool flag = false;
inline void add(int from, int to) {
edge[++num_edge].to = to;
edge[num_edge].next = head[from];
head[from] = num_edge;
}
void dfs(int u, int fa) {
dfn[u] = low[u] = ++tim;
int son = 0;
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (!dfn[v]) {
dfs(v, fa);
low[u] = min(low[u], low[v]);
if (low[v] >= dfn[u] && u != fa) {
cnt[u] = 1;
}
if (u == fa) son++;
}
else low[u] = min(low[u], dfn[v]);
}
if (son >= 2 && u == fa) cnt[u] = 1;
}
bool check(int k) {
queue<int> q;
// cout << "11111" << endl;
memset(vis , 0, sizeof(vis));
vis[s] = 1; q.push(s);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
// cout << v << endl;
if (v == e) return false;
if (v == k) continue;
if (!vis[v]) {
q.push(v);
vis[v] = 1;
}
}
}
return true;
}
int main() {
// freopen("dfnIn.in","r",stdin);
// freopen("dfnin.out","w",stdout);
n = read();
while (scanf("%d %d", &a, &b)) {
if (a == 0 && b == 0) break;
add(a, b);
add(b, a);
}
s = read(), e = read();
for (int i = 1; i <= n; ++i) {
if (!dfn[i]) dfs(i, i);
}
for (int i = 1; i <= n; ++i) if (cnt[i] > 0) t[++ss] = i;
// for (int i = 1; i <= ss; ++i) printf("%d ", t[i]);
// printf("\n");
for (int i = 1; i <= ss; ++i) {
if (check(t[i])) {
// cout << t[i] << endl;
printf("%d\n", t[i]);
flag = true;
system("PAUSE");
return 0;
}
}
if (!flag) printf("No solution\n");
// system("PAUSE");
return 0;
}
题解2
考虑我们有一个u点,它连了一个v点,那么u点需要满足4个条件。
1、u不是起点终点。因为题目要求在中间服务器上建嗅探器。
2、u是割点。废话
3、终点(y)的dfn应该大于等于v点的dfn,因为要确保终点在v点或之后被访问到,即u点为必经的点。
4、终点(y)的low应该大于等于u点的dfn,因为要确保终点必须要经过u点。
code2
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 100;
typedef long long ull;
typedef pair <int, int > pii;
const int inf = 0x3f3f3f3f;
inline int read() {
int s = 0, w = 1;
char ch = getchar();
while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }
while (isdigit(ch)) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
return s * w;
}
int n, a, b;
int ans = inf;
struct Edge { int next, to; } edge[maxn];
int num_edge = 0, tim = 0, ss = 0, s, e;
int head[maxn], low[maxn], dfn[maxn], cnt[maxn], vis[maxn];
int t[maxn], point = inf;
bool flag = false;
inline void add(int from, int to) {
edge[++num_edge].to = to;
edge[num_edge].next = head[from];
head[from] = num_edge;
}
void tarjan(int u) {
dfn[u] = low[u] = ++tim;
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
if (u != s && u != e) {
if (dfn[u] <= low[v] && dfn[v] <= dfn[e] && low[e] >= dfn[s]) {
ans = min(ans, u);
}
}
}
else low[u] = min(low[u], dfn[v]);
}
}
int main() {
n = read();
while (scanf("%d %d", &a, &b)) {
if (a == 0 && b == 0) break;
add(a, b);
add(b, a);
}
s = read(), e = read();
tarjan(s);
if (ans == inf) printf("No solution\n");
else printf("%d\n", ans);
return 0;
}