【xsy1378】 水题7号 贪心

题目大意:有m组约束关系(xi,yi),你要构造一个排列,满足数xi出现在数yi前面,请使得这个排列字典序最小,请输出这个排列。无解请输出-1。

数据范围:n,m105

 

我们把约束关系(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 }
复制代码

 

 

posted @   AlphaInf  阅读(115)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示