习题:Berland and the Shortest Paths(最短路树)

题目

传送门

思路

从1号节点到每一个节点的最短路是确定的,并且下界一定是所有的最短路长度相加,

我们考虑能不能到达下界

对于某一个节点,如果他想到达最短路,他一定是从某一个节点+1转移过来,并且这一个节点也需要是最短路,此时需要占用一条边的代价

类比,如果要将n个节点都达到最短路,必然需要n-1条边,同时,我们只需要保证第i号节点的前驱是满足条件的即可

我们把这种东西叫做最短路树

也就是下界是一定可以达到的,在之后我们对于每一个节点随便选一个前驱即可

代码

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
namespace IO
{
    void read(int &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')  
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void write(int x)
    {
        if(x<10)
            putchar(x+'0');
        else
        {
            write(x/10);
            putchar(x%10+'0');
        }
    }
}
using namespace IO;
struct node
{
    int e;
    int id;
};
int n,m,k;
int used[200005],dis[200005],cnt;
bool mem[200005];
queue<int> q;
vector<node> g[200005];
vector<int> pre[200005];
long long t=1;
void bfs(int s)
{
    memset(dis,0x3f,sizeof(dis));
    q.push(s);
    dis[s]=0;
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        if(used[t])
            continue;
        used[t]=1;
        for(int i=0;i<g[t].size();i++)
        {
            int v=g[t][i].e;
            if(dis[v]>dis[t]+1)
            {
                dis[v]=dis[t]+1;
                q.push(v);
            }
        }
    }
}
void build()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<g[i].size();j++)
        {
            if(dis[i]+1==dis[g[i][j].e])
                pre[g[i][j].e].push_back(g[i][j].id);
        }
    }
}
void dfs(int dep)
{
    if(dep==n+1)
    {
        cnt++;
        for(int i=1;i<=m;i++)
            write(mem[i]);
        putchar('\n');
        if(cnt==k)
            exit(0);
        return;
    }
    for(int i=0;i<pre[dep].size();i++)
    {
        mem[pre[dep][i]]=1;
        dfs(dep+1);
        mem[pre[dep][i]]=0;
    }
}
int main()
{
    read(n);read(m);read(k);
    for(int i=1,u,v;i<=m;i++)
    {
        read(u);read(v);
        g[u].push_back((node){v,i});
        g[v].push_back((node){u,i});
    }
    bfs(1);
    build();
    for(int i=2;i<=n;i++)
    {
        t=t*pre[i].size();
        if(t>k)
            break;
    }
    k=min(1ll*k,t);
    write(k);
    putchar('\n');
    dfs(2);
    return 0;
}
posted @ 2020-08-23 18:58  loney_s  阅读(96)  评论(0)    收藏  举报