Codeforces Round #796 B

B. Railway System

我们显然可以用m次询问求出每条边的权重
我们再考虑最小生成树的过程 对于每一次我们把当前最小边加入
我们考虑与最大生成树的区别 要是该点本该是mst内的 那么最大生成树与最小生成树相同
如果不是 那么两个端点连通 这样会形成环
而我们不知道这一次最小生成树的大小
但是我们知道上一次最小生成树的大小
所以我们得出了
要是当前query-mst=当前边大小 等价于 最大生成树与最小生成树相同 所以我们把这条边加入
反之就是不等于 形成环 而我们这个query-mst肯定是不等于当前边大小 因为我们这条边因为排序之后
现在是该树中最大的一条 而我们形成环 肯定是该边-最小边!=该边大小

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
const int M = 998244353;
const int mod = 998244353;
int up(int a,int b){return a<0?a/b:(a+b-1)/b;}
#define int long long
#define endl '\n'
#define all(x) (x).begin(),(x).end()
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
#define _ 0
#define pi acos(-1)
#define INF 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int n,m;
pair<int,int>w[N];
int query(string s){
    cout<<"? "+s<<endl;
    int x;cin>>x;
    return x;
}
void solve() {
    cin>>n>>m;
    string s;
    for(int i=1;i<=m;i++)s.push_back('0');
    for(int i=0;i<m;i++){
        if(i)s[i-1]='0';
        s[i]='1';
        w[i].first=query(s);w[i].second=i;
    }
    s[m-1]='0';
    sort(w,w+m);
    int mst=0;
    for(int i=0;i<m;i++){
        s[w[i].second]='1';
        int t=query(s);
        if(t-mst==w[i].first){
            mst=t;
        }else s[w[i].second]='0';;
    }
    cout<<"! "<<mst<<endl;
}
signed main(){
    //fast
    int t;t=1;//cin>>t;
    while(t--) {
        solve();
    }
    return ~~(0^_^0);
}
posted @ 2022-10-09 20:26  ycllz  阅读(26)  评论(0)    收藏  举报