题解 CF1819E 【Roads in E City】
小清新交互题。
题解
首先观察题目中所给的询问操作到底有什么用处。发现,如果整张图是一个连通图,那么每次询问的结果必定是
下文中所有「连通」、「不连通」、「桥」的概念全是在只考虑图上关键边的情况下。
假设原图本来是一个连通图,我们把某条边
然而无向连通图还是不太好下手。考虑随便选取其中一个生成树。那么生成树上每条边肯定都是桥。现在要检查不在生成树上的一条边
不过怎么获得原图的一个生成树呢?可以考虑枚举每条边,判断它是不是桥,如果不是桥就把它删掉,这样剩下来的边肯定能组成一个生成树,正确性比较显然。当然在这个过程中可能会有关键边被删掉,所以需要按照上述步骤在找到生成树后检查被删除的边。
总操作次数
参考代码
#include<bits/stdc++.h>
#define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
#define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
using namespace std;
typedef long long i64;
const int INF = 2147483647;
const int MAXN= 2e3 + 3;
const int MAXM= 2e3 + 3;
int U[MAXM], V[MAXM], n, m, k = 20;
bool check_cut(int x){
int u = U[x], v = V[x], t;
bool f = false;
up(1, k, i){
cout << "? " << u << endl; cin >> t; f |= (t == 0);
cout << "? " << v << endl; cin >> t; f |= (t == 0);
if(f == true) break;
}
return f;
}
vector <pair<int, int> > X[MAXN];
int F[MAXN], D[MAXN]; bool E[MAXN], I[MAXN];
void dfs(int u, int f){
for(auto &e : X[u]) if(e.second != f){
int v = e.second;
F[v] = e.first, D[v] = D[u] + 1, dfs(v, u);
}
}
int main(){
int T; cin >> T;
up(1, T, _){
cin >> n >> m;
up(1, n, i) F[i] = D[i] = 0, X[i].clear();
up(1, m, i) E[i] = I[i] = 0;
up(1, m, i){
cin >> U[i] >> V[i];
}
up(1, m, i){
int u = U[i], v = V[i];
cout << "- " << i << endl;
if(check_cut(i)){
X[u].push_back({i, v});
X[v].push_back({i, u});
cout << "+ " << i << endl;
I[i] = true;
} else E[i] = true;
}
dfs(1, 0);
// up(1, n, i) printf("%d ", F[i]); puts("");
up(1, m, i) if(E[i]){
int u = U[i], v = V[i];
if(D[u] < D[v]) swap(u, v);
cout << "- " << F[u] << endl;
cout << "+ " << i << endl;
if(!check_cut(i)) I[i] = true;
cout << "- " << i << endl;
cout << "+ " << F[u] << endl;
}
cout << "!";
up(1, m, i) cout << " " << I[i];
cout << endl;
int f; cin >> f; if(f == 0) return 0;
}
return 0;
}