【xsy1378】 水题7号 贪心
题目大意:有m组约束关系(xi,yi),你要构造一个排列,满足数xi出现在数yi前面,请使得这个排列字典序最小,请输出这个排列。无解请输出-1。
数据范围:n,m≤105
我们把约束关系(xi,yi)视作从yi连向xi的有向边,于是我们得到了一个有向图,无解情况下该图会存在环。
我们对这个有向图进行拓扑排序即可,只不过每次出队的点是当前队列中编号最大的点。
我们开一个数组ans,记ansi表示第i次出队的点的编号。
若原图中存在环,显然|ans|≠n,我们可以通过该性质判断是否有解。
否则倒着输出ans数组即可。
关于正确性可以这么理解:当第x个点出队时,所有依赖于该点的点都出队了,且当前编号大于它的点都出队了。
1 #include<bits/stdc++.h> 2 #define M 100005 3 using namespace std; 4 5 vector<int> v[M]; 6 int n,m,vis[M]={0}; 7 int ans[M]={0},in[M]={0},cnt=0; 8 priority_queue<int> q; 9 int Main(){ 10 memset(in,0,sizeof(in)); 11 memset(ans,0,sizeof(ans)); cnt=0; 12 for(int i=0;i<M;i++) v[i].clear(); 13 scanf("%d%d",&n,&m); 14 for(int i=1;i<=m;i++){ 15 int x,y; scanf("%d%d",&x,&y); 16 v[y].push_back(x); in[x]++; 17 } 18 for(int i=1;i<=n;i++) if(in[i]==0) q.push(i); 19 while(!q.empty()){ 20 int u=q.top(); q.pop(); 21 ans[++cnt]=u; 22 int siz=v[u].size(); 23 for(int i=0;i<siz;i++){ 24 int V=v[u][i]; 25 in[V]--; 26 if(in[V]==0) q.push(V); 27 } 28 } 29 if(n!=cnt){ 30 printf("Impossible!\n"); 31 return 0; 32 } 33 for(int i=n;i;i--) printf("%d ",ans[i]); 34 } 35 int main(){ 36 int t; cin>>t; 37 while(t--) Main(); 38 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!