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();
    if(ch=='-') ch=getchar(),fh=-1;
    else fh=1;
    while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    x*=fh;
}

const int maxn=200007;
const int maxm=400007;
const int INF=0x3f3f3f3f;

int n,m,k;
int Head[maxn],to[maxm],Next[maxm],tot,w[maxm];

void add(int x,int y){
    to[++tot]=y,Next[tot]=Head[x],Head[x]=tot,w[tot]=1;
}

int dis[maxn];
bool vis[maxn];

priority_queue< pair<int,int> > q;
#define pii(x,y) make_pair(x,y)

void dijkstra(){
    memset(dis,0x3f,sizeof(dis));
    q.push(pii(0,1));dis[1]=0;
    while(q.size()){
        int x=q.top().second;q.pop();
        if(vis[x]) continue;vis[x]=1;
        for(int i=Head[x];i;i=Next[i]){
            int y=to[i];
            if(dis[y]>dis[x]+w[i]){
                dis[y]=dis[x]+w[i];
                q.push(pii(-dis[y],y));
            }
        }
    }
}

int ans=1;

vector<int>g[maxn];
int val[maxn];
void build(){
    for(int x=1;x<=n;x++){
        for(int i=Head[x];i;i=Next[i]){
            int y=to[i];
            if(dis[y]==dis[x]+w[i]){
                val[y]++;
                g[y].push_back((i+1)>>1);
            }
        }
    }
    for(int i=1;i<=n;i++){
        if(val[i]) ans=ans*val[i];
        if(ans>=k){
            ans=k;return;
        }
    }
}

bool v[maxm];
int md;

void dfs(int x){
    if(x==n+1){
        for(int i=1;i<=tot;i+=2) printf("%d",v[(i+1)>>1]);
        puts("");++md;
        if(md==ans) exit(0);return;
    }
    for(int i=0;i<g[x].size();i++){
        v[g[x][i]]=1;dfs(x+1);v[g[x][i]]=0;
    }
}

int main(){
    read(n);read(m);read(k);
    for(int i=1,x,y;i<=m;i++){
        read(x);read(y);
        add(x,y);add(y,x);
    }
    dijkstra();build();
    printf("%d\n",ans);
    dfs(2);
    return 0;
}

原文地址:https://www.cnblogs.com/liubainian/p/11808905.html

时间: 2024-10-09 17:25:11

CF1005F Berland and the Shortest Paths 最短路树计数的相关文章

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

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之间

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

uva 1416 Warfare And Logistics (最短路树)

uva 1416 Warfare And Logistics Description The army of United Nations launched a new wave of air strikes on terrorist forces. The objective of the mission is to reduce enemy's logistical mobility. Each air strike will destroy a path and therefore inc

UVA 1416 最短路树

Warfare And Logistics The army of United Nations launched a new wave of air strikes on terroristforces. The objective of the mission is to reduce enemy's logistical mobility. Each airstrike will destroy a path and therefore increase the shipping cost

POJ1122_FDNY to the Rescue!(逆向建图+最短路树)

FDNY to the Rescue! Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 2368   Accepted: 721 Description The Fire Department of New York (FDNY) has always been proud of their response time to fires in New York City, but they want to make the

HDU - 2433 Travel (最短路树)

题目大意:有N个点,M条边,每次删掉一条边,问删掉该边后,所有点之间的最短路的和是多少 解题思路:刚开始就想,删掉一次floyd一次,结果可想而之,TLE了 后来看了别人的,发现了一种叫做最短路树的东西. 就是先求出以每个点为源点的最短路并纪录该点到每个点的距离和,和每个点的pre,这样的话,就预处理好了 因为要删掉边,前面我们已经预处理好了最短路树的pre,也就是说,就可以依次判断删除的边是否在最短路树上,只要你要删除的边不在该最短路树上,那么就没有影响了,可以直接用前面纪录的数据 如果要删掉

Warfare And Logistics UVALive - 4080 (最短路树)

Warfare And Logistics UVALive - 4080 题意:给n个点m条边.令c为每对节点的最短路长度之和.要求删除一条边后使得新的c值c'最大,不连通的两点对短路视为L. [如果每次删除一条边,要跑m次dijkstra,其实其中很多次都对最短路没有影响,因为删掉的边不在最短路里] [因此,可以每次删除最短路树中的一条边,需要跑n次,复杂度降低到可接受程度] 1 #include <bits/stdc++.h> 2 #define LL long long 3 using

UVA 1416 - Warfare And Logistics(最短路树)

UVA 1416 - Warfare And Logistics 题目链接 题意:给定一个无向图,每个边一个正权,c等于两两点最短路长度之和,现在要求删除一边之后,新图的c值最大的是多少 思路:直接枚举删边,每次做一次dijkstra的话复杂度太高,其实如果建好最短路树,如果删去的边在最短路树上,才需要去做,这样复杂度就优化到(n^2mlog(n)),勉强可以接受 代码: #include <cstdio> #include <cstring> #include <vecto