这题不错...
首先,不难看到他想让你求出的是最短路树
然后,考虑到所有边权均为1,所以可以采用bfs直接生成最短路树
至于方案的储存,可以在加边的时候同时记录边的编号,然后对每个点维护一个能转移他的最短路的边的编号的集合,这样总的方案数就是所有的集合大小的乘积
然后用dfs在每个集合中选一个元素输出即可
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <queue> #include <stack> using namespace std; struct Edge { int next; int to; int num; }edge[400005]; int head[200005]; int dep[200005]; vector <int> v[200005]; int used[200005]; int cnt=1; int n,m,k; void init() { memset(head,-1,sizeof(head)); cnt=1; } void add(int l,int r,int v) { edge[cnt].next=head[l]; edge[cnt].to=r; edge[cnt].num=v; head[l]=cnt++; } void bfs(int rt) { queue <int> M; M.push(rt); dep[rt]=0; while(!M.empty()) { int u=M.front(); M.pop(); for(int i=head[u];i!=-1;i=edge[i].next) { int to=edge[i].to; if(!dep[to]) { dep[to]=dep[u]+1; v[to].push_back(edge[i].num); M.push(to); }else if(dep[to]==dep[u]+1) { v[to].push_back(edge[i].num); } } } } int cct=0,tot=1; void dfs(int dep) { if(dep==n+1) { for(int i=1;i<=m;i++) { printf("%d",used[i]); } printf(" "); cct++; if(cct==tot) { exit(0); } return; } for(int i=0;i<v[dep].size();i++) { used[v[dep][i]]=1; dfs(dep+1); used[v[dep][i]]=0; } } inline int read() { int f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int main() { n=read(),m=read(),k=read(); init(); for(int i=1;i<=m;i++) { int x=read(),y=read(); add(x,y,i); add(y,x,i); } bfs(1); for(int i=2;i<=n;i++) { if((long long)tot*v[i].size()>k) { tot=k; break; }else { tot*=v[i].size(); } } printf("%d ",tot); dfs(2); return 0; }