D - … (Double Dots)(贪心&最短路)
思路:一开始以为是单源最短路水题,每次更新储存下相邻的结点即可,这种做法能AC,但是复杂了。
后来看了别人写的,跟最短路没什么关系,因为题目保证是个连通图,所以必有答案,又因为相连的点距离恒为1,所以贪心即可,与1相连的点的答案必定是1,然后不断向外扩散即可。。
做法:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,inf=0x3f3f3f3f;
#define mst(a) memset(a,0,sizeof a)
int n,d[N],vis[N],sign[N],m;
vector<int>e[N<<1];
void spfa(){
queue<int>q;
for(int i=1;i<=n;i++) d[i]=inf;
q.push(1);vis[1]=1,d[1]=0;
while(q.size()){
int u=q.front();q.pop();vis[u]=0;
for(auto v:e[u]){
if(d[v]>d[u]+1){
d[v]=d[u]+1;
sign[v]=u;
if(!vis[v]) q.push(v),vis[v]=1;
}
}
}
int ok=0;
for(int i=2;i<=n;i++)
if(d[i]==inf){
ok=1;
break;
}
if(ok) puts("No");
else {
puts("Yes");
for(int i=2;i<=n;i++)
printf("%d\n",sign[i]);
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1,u,v;i<=m;i++){
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
spfa();
return 0;
}
贪心做法:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
#define mst(a) memset(a,0,sizeof a)
vector<int>e[N];
int n,m,ans[N];
int main(){
scanf("%d%d",&n,&m);
for(int i=1,u,v;i<=m;i++){
scanf("%d%d",&u,&v);
e[u].push_back(v),e[v].push_back(u);
}
ans[1]=1;
queue<int>q;
q.push(1);
while(q.size()){
int u=q.front();q.pop();
for(auto v:e[u])
if(!ans[v]) ans[v]=u,q.push(v);
}
puts("Yes");
for(int i=2;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}