Codeforces Round #496 (Div. 3) F. Berland and the Shortest Paths[思维+图论]

F. Berland and the Shortest Paths

题意:一张图有n个顶点,m条边,现在要求选择n-1条边,输出<=k个方案.

每个方案满足:顶点1到任何1个顶点的距离 总和 最小.

思路:每个顶点(除了1),有选择1条边的机会.先bfs求出1到所有顶点的最短距离,假如 dis[u]==dis[v]+1 其中v为相邻顶点,则选这条边,能够最小化答案.那么对于u来说,选择(u,v1) (u,v2) (u,v3)同样能最小化答案.假如问答案有多少种,直接乘起来,这里只要求至多k组,并且k*t<=1e6

#include<bits/stdc++.h>
#define PI acos(-1.0)
#define pb push_back
#define F first
#define S second
using namespace std;
typedef long long ll;
const int N=2e5+5;
const int MOD=1e9+7;
ll a[N],sum[N];
int n,m,k;
int dis[N];
vector<pair<int,int> >edge[N];
vector<int> can[N];
void bfs(int st){
    for(int i=1;i<=n;i++)   dis[i]=1e9+9;
    queue <int> q;
    dis[1]=0;
    q.push(1);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(auto t : edge[u]){
            int v=t.F;
            if(dis[u]+1<dis[v]){
                dis[v]=dis[u]+1;
                q.push(v);
            }
        }
    }
    return ;
}
char res[N];
vector<string> ans;
void dfs(int u){
    if((int)ans.size()>=k)  return ;
    if(u==n+1){        ans.pb(res+1);
        return ;
    }
    for(auto t:can[u]){
        res[t]='1';
        dfs(u+1);
        res[t]='0';
    }
    return ;
}

int main(void){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);

    cin >>n >>m >>k ;
    for(int i=1;i<=m;i++){
        int u,v;

        cin >>u>>v;
        edge[u].pb({v,i});
        edge[v].pb({u,i});
    }
    bfs(1);
//    cout <<"here"<<endl;
    for(int u=2;u<=n;u++){
        for(auto t : edge[u]){
            int v=t.F;
            if(dis[u]==dis[v]+1){
                can[u].pb(t.S);
            }
        }
    }
    for(int i=1;i<=m;i++)   res[i]='0';
    dfs(2);
    cout << (int)ans.size()<<endl;
    for(int i=0;i<(int)ans.size();i++){
        cout << ans[i]<<endl;
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/haipai1998/article/details/80985366