Codeforces 1005 F - Berland and the Shortest Paths

F - Berland and the Shortest Paths

思路:

bfs+dfs

首先,bfs找出1到其他点的最短路径大小dis[i]

然后对于2...n中的每个节点u,找到它所能改变的所有前驱(在保证最短路径不变的情况下),即找到v,使得dis[v] + 1 == dis[u],并把u和v所连边保存下来

最后就是dfs递归暴力枚举每个点的前驱,然后输出答案

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<int,pii>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 2e5 + 5;
int n, m, k;
vector<pii>g[N];
vector<int>pre[N];
int dis[N];
bool vis[N];
char s[N];
vector<string>res;
void bfs(int st) {
    queue<pii>q;
    dis[1] = 0;
    vis[1] = true;
    q.push({1, 0});
    while(!q.empty()) {
        pii p = q.front();
        q.pop();
        for (int i = 0; i < g[p.fi].size(); i++) {
            int v = g[p.fi][i].fi;
            if(!vis[v]) {
                vis[v] = true;
                dis[v] = p.se + 1;
                q.push({v, p.se + 1});
            }
        }
    }
}
void dfs(int u) {
    if((int) res.size() >= k) return ;
    if(u > n) {
        res.pb(s+1);
        return ;
    }
    for (int i = 0; i < pre[u].size(); i++) {
        s[pre[u][i]] = ‘1‘;
        dfs(u+1);
        s[pre[u][i]] = ‘0‘;
    }
}
int main() {
    fio;
    int u, v;
    cin >> n >> m >> k;
    for (int i = 1; i <= m; i++) {
        cin >> u >> v;
        g[u].pb({v, i});
        g[v].pb({u, i});
    }
    bfs(1);
    for (int i = 2; i <= n; i++) {
        for (int j = 0; j < g[i].size(); j++) {
            pii p = g[i][j];
            if(dis[p.fi]+1 == dis[i]) pre[i].pb(p.se);
        }
    }
    for (int i = 1; i <= m; i++) s[i] = ‘0‘;
    dfs(2);
    cout << (int)res.size() << endl;
    for (int i = 0; i < res.size(); i++) cout << res[i] << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/widsom/p/9290144.html

时间: 2024-08-01 20:53:36

Codeforces 1005 F - Berland and the Shortest Paths的相关文章

Berland and the Shortest Paths CodeForces - 1005F(最短路树)

最短路树就是用bfs走一遍就可以了 d[v] = d[u] + 1 表示v是u的前驱边 然后遍历每个结点 存下它的前驱边 再用dfs遍历每个结点 依次取每个结点的某个前驱边即可 #include <bits/stdc++.h> #define mem(a, b) memset(a, b, sizeof(a)) using namespace std; const int maxn = 1e6+10, INF = 0x7fffffff; int n, m, k, cnt; int head[ma

Codeforces 1005F Berland and the Shortest Paths 【最短路树】【性质】

其实是一道裸题,如果没学过最短路树的话会比较难做,要想很久想到关键性质才能做出来. 最短路树顾名思义,就是从一个图中生成出来一棵树,使得每个顶点到root的距离是单源最短路.如果有这样的树的话,那可见这样的树是符合题意的. 怎么生成这样的树呢?关键在于记录前驱father,一个距离root最短路是6的点必定从一个距离root最短路是5的点到达(这两个点之间一定会有一条边).所以我们对于所有顶点 2-n,每个顶点u我们找dis[u] = dis[v]+1的情况,这样的话v就是u的前驱.若v,u之间

CF1005F Berland and the Shortest Paths 最短路树计数

问题描述 LG-CF1005F 题解 由题面显然可得,所求即最短路树. 所以跑出最短路树,计数,输出方案即可. \(\mathrm{Code}\) #include<bits/stdc++.h> using namespace std; template <typename Tp> void read(Tp &x){ x=0;char ch=1;int fh; while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar

Codeforces Round #550 (Div. 3) F. Graph Without Long Directed Paths

F. Graph Without Long Directed Paths time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given a connected undirected graph consisting of nn vertices and mm edges. There are no self-lo

Codeforces 727 F. Polycarp&#39;s problems

Description 有一个长度为 \(n\) 有正负权值的序列,你一开始有一个值,每次到一个权值就加上,最少需要删掉多少数值才能到序列末尾.\(n \leqslant 750,m \leqslant 2 \times 10^5\) Sol DP+二分. 发现这个东西有后效性,就是前面选不选会影响后面的决策,并且权值太大无法记录. 但是我们可以倒着做,因为后面的决策无法影响前面的决策. \(f[i][j]\) 表示到 \(i\) 删掉 \(j\) 个至少需要的初始权值. 因为初始权值非负,所以

Codeforces 835 F. Roads in the Kingdom

\(>Codeforces\space835 F. Roads in the Kingdom<\) 题目大意 : 给你一棵 \(n\) 个点构成的树基环树,你需要删掉一条环边,使其变成一颗树,并最小化删掉环边后的树的直径. \(n \leq 2 \times 10^5\) 树的边权 $ \leq 10^9 $ 解题思路 : 考虑最终树的直径可能由两部分组成,答案是其中的最大值 第一种就是外向树内的直径的最大值,这个只需要随便\(dp\)一下即可,这里不过多讨论 第二种情况树的直径经过原来的环,

Codeforces 1166 F. Vicky&#39;s Delivery Service 并查集+set

题意:有n个点,m条边,边有c种颜色,q次操作. 每个边都有一种颜色. 然后操作有两种,一种是再加一条边,另一种是查询能否从x达到y. 移动的限制是,连着走两步必须是同一种颜色,如果走奇数步,最后一步可以是任意颜色. 例子:1-2-3-4-5-6. 这个题颜色种类很多,我是用map<int,vector<int>>来存边. 我们首先可以想到 对于点x同种颜色连着的点都是可以相互移动的,所以我们可以用这种方法将它们用并查集合并,所以我们也可以直接map<int,int>来

# codeforces 1272 F. Two Bracket Sequences(三维dp + bfs)

codeforces 1272 F. Two Bracket Sequences(三维dp + bfs) 题目大意 输入两个括号序列 s,t(不一定合法),你需要构造一个尽可能短的合法括号序列使得s,t 都是这个序列的子序列(子序列意味着不用连续) 解题思路 dp[i][j][k]表示匹配到s的第i个字符,匹配到t的第j个字符,并且此时(的个数比)多k个的时候的最小合法序列长度,k的上限是200(s和t中最多200个(或者)). 状态转移: 枚举答案合法序列的每一位是放置(或者) ? 放置(,如

Codeforces Round #617 (Div. 3)F. Berland Beauty

题意: 给一棵树,边权未知,现在给m组约束,每组约束给出从u到v路径中的最小值,现在让你给出一组边权,使得符合之前的约束,不能给出输出-1 思路: 因为n较小,对于每组约束我们可以直接暴力修改路径上的权值,如果边的权值小于当前约束的最小值,则将权值修改,最后再根据每组约束暴力走一遍路径看路径是否满足要求,如果不满足则输出-1,最后还得对那些没有修改过的边随意赋值 #include<iostream> #include<algorithm> #include<vector>