习题: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;
}

浙公网安备 33010602011771号