HDU 4857 逃生 && Codeforces 825 E. Minimal Labels 逆向拓扑序+优先队列

来源:互联网 发布:php gzip 解压缩 编辑:程序博客网 时间:2024/05/21 13:21

传送门:HDU4857

思路:很容易看出来是个拓扑序,然而我用队列、优先队列、排序等等什么方法求拓扑序都wa。。

正解:应该反向建图,由在后面的指向在前面的,这样每次取出来的一定是可以放在最后面的,如果同时有多个入度为0,则取编号较大的,这一过程可以用优先队列维护。(注意,将编号最小的尽量放在前面和字典序最小不一样!见下面样例)

虽然证明不了这样是反着做是对的,但是很简单一组数据就能证明正向做不可行:

1

3 2

3 1

3 1

答案应为3 1 2

代码:

#include<bits/stdc++.h>#include<iostream>#include<vector>#include<queue>using namespace std;#define MAXN 100010vector<int>g[MAXN],ans;int n,m,k=1;int in[MAXN];priority_queue<int>q;void topo_sort(){    while(!q.empty())q.pop();    int s,u,v;    for(int i=1;i<=n;i++)    if(in[i]==0)    {        q.push(i);    }    while(!q.empty())    {        u=q.top();q.pop();        ans.push_back(u);        for(int i=0;i<g[u].size();i++)        {            v=g[u][i];            in[v]--;            if(in[v]==0)                q.push(v);        }    }}int main(){    int T,u,v;    cin>>T;    while(T--)    {        k=1;        ans.clear();        memset(in,0,sizeof(in));        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++)            g[i].clear();        for(int i=0;i<m;i++)        {            scanf("%d%d",&u,&v);            g[v].push_back(u);            in[u]++;        }        topo_sort();        for(int i=n-1;i>=0;i--)            printf("%d%c",ans[i]," \n"[i==0]);    }}

好好琢磨琢磨似乎有那么点意思。


传送门:E. Minimal Labels

题意:给出一个DAG图,让你给每个顶点标号,标号的条件:

1.  如果有一条边(u,v),则lable[u]<lable[v]

2.  满足上面条件的情况下使得字典序最小。

这题与上面那题的思路和做法都是一样的,但为什么问题不一样呢?我个人认为是因为上面的题让输出的是拓扑排序后的序列,而这个题输出的是拓扑排序后序列中每个元素的标号,也就是说上面的题中如果把每个元素的标号按顺序输出来也是字典序最小的。

代码:

#include<bits/stdc++.h>  #include<iostream>  #include<vector>  #include<queue>  using namespace std;  #define MAXN 100010  vector<int>g[MAXN],ans(MAXN);  int n,m,k=1;  int in[MAXN];  priority_queue<int,vector<int>,less<int> >q;  void topo_sort()  {      while(!q.empty())q.pop();    int s,u,v;      for(int i=1;i<=n;i++)      if(in[i]==0)     {          q.push(i);    }      while(!q.empty())      {          u=q.top();q.pop();        ans[u]=k--;  //注意这里是u点的标号为k        for(int i=0;i<g[u].size();i++)          {              v=g[u][i];              in[v]--;              if(in[v]==0)                  q.push(v);          }      }  }  int main()  {      int T,u,v;           ans.clear();          memset(in,0,sizeof(in));          scanf("%d%d",&n,&m);  k=n;        for(int i=0;i<m;i++)          {              scanf("%d%d",&u,&v);              g[v].push_back(u);            in[u]++;          }          topo_sort();        for(int i=1;i<=n;i++)              printf("%d%c",ans[i]," \n"[i==n]);} 

阅读全文
0 0
原创粉丝点击