拓扑排序+优先队列Labeling Balls

poj 3687 Labeling Balls

题意就是给出n个球   会有k个条件限制 a b  a号球会在b号前面  否则按大小顺序排  小号的在前面

首先这道题要求反向建图  让我纳闷了很久。。在什么情况下要求反向建图呢。。求人指点

学习的第一种解法并没有用到优先队列  而是模拟那个过程选取最大的没有遍历过的 

那个存储的值及下标之间的关系还要再思考思考

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>

#define eps 1e-8
#define op operator
#define MOD  10009
#define MAXN  100100

#define FOR(i,a,b)  for(int i=a;i<=b;i++)
#define FOV(i,a,b)  for(int i=a;i>=b;i--)
#define REP(i,a,b)  for(int i=a;i<b;i++)
#define REV(i,a,b)  for(int i=a-1;i>=b;i--)
#define MEM(a,x)    memset(a,x,sizeof a)
#define ll __int64

using namespace std;

int rd[210];
int map[210][210];
int sta[210];
int vis[210];

int main()
{
//freopen("ceshi.txt","r",stdin);
    int tc;
    scanf("%d",&tc);
    while(tc--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        MEM(rd,0); MEM(map,0);  MEM(vis,0);
        for(int i=0;i<m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(!map[y][x])
            {
                map[y][x]=1;
                rd[x]++;
            }
        }
        int top=-1;
        bool flag=1;
        for(int i=n;i>=1;i--)
        {
            int q=0;
            for(int j=n;j>=1;j--)
            {
                if(rd[j]==0&&!vis[j])
                {
                    q=j;  break;
                }
            }
            if(q==0)
            {
                flag=0;
                printf("-1\n");
                break;
            }
            vis[q]=1;  sta[q]=i;   //要求的是 标签对应最小重量。     拓扑序下标就是重量。。
            for(int j=n;j>=1;j--)
                if(map[q][j])  rd[j]--;
        }
//        cout<<"ttt"<<top<<endl;
        if(flag)
        {
            for(int i=1;i<=n;i++)
                printf("%d ",sta[i]);
            printf("\n");
        }
    }
    return 0;
}

然后就是借助优先队列进行解题   同样的 存储的值以及下标之间的关系需要思考

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <queue>
#include <vector>

#define eps 1e-8
#define op operator
#define MOD  10009
#define MAXN  100100

#define FOR(i,a,b)  for(int i=a;i<=b;i++)
#define FOV(i,a,b)  for(int i=a;i>=b;i--)
#define REP(i,a,b)  for(int i=a;i<b;i++)
#define REV(i,a,b)  for(int i=a-1;i>=b;i--)
#define MEM(a,x)    memset(a,x,sizeof a)
#define ll __int64

using namespace std;

int mp[210][210];
int rd[210];
int ans[210];

int main()
{
//freopen("ceshi.txt","r",stdin);
    int tc;
    scanf("%d",&tc);
    while(tc--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        MEM(mp,0);
        MEM(rd,0);
        bool flag=1;
        for(int i=0;i<m;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            if(!mp[b][a])
            {
                if(a==b)  flag=0;
                mp[b][a]=1;
                rd[a]++;
            }
        }
//        if(!flag)
//        {
//             printf("-1\n");  continue;
//        }
        priority_queue<int> q;
        for(int i=1;i<=n;i++)
            if(rd[i]==0)  q.push(i);
//        int top=0;
        int index=n;
        while(!q.empty())
        {

            int tmp=q.top();
//            cout<<"top"<<top<<"   "<<tmp<<endl;
            q.pop();
            for(int i=1;i<=n;i++)
            {
                if(mp[tmp][i]==1)
                {
                    rd[i]--;
                    if(rd[i]==0)  q.push(i);
                }
            }
            ans[tmp]=index;
            index--;
//            cout<<"top"<<top<<"   "<<tmp<<endl;
        }
//        cout<<top<<endl;
        if(index>0)  printf("-1\n");
        else
        {
            printf("%d",ans[1]);
            for(int i=2;i<=n;i++)
                printf(" %d",ans[i]);
            puts("");
        }
    }
    return 0;
}



第二题是hdu上的一道题  4857  题意差不多 

但是由于这题给的数据范围比较大 需要借助vector进行存储  数组开不了 同样的也是需要反向建图

这题与上面那题存储的方式不同 这题直接按照拓扑排序常规方法进行存储即可   

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <queue>

#define eps 1e-8
#define op operator
#define MOD  10009
#define MAXN  30010

#define FOR(i,a,b)  for(int i=a;i<=b;i++)
#define FOV(i,a,b)  for(int i=a;i>=b;i--)
#define REP(i,a,b)  for(int i=a;i<b;i++)
#define REV(i,a,b)  for(int i=a-1;i>=b;i--)
#define MEM(a,x)    memset(a,x,sizeof a)
#define ll __int64

using namespace std;

int rd[MAXN];
vector<int> mp[MAXN];
int ans[MAXN];

struct cmp
{
    bool operator() (int &a,int &b)
    {
        return a<b;  //´óÖµÓÅÏÈ£»
    }
};

int main()
{
//freopen("ceshi.txt","r",stdin);
    int tc;
    scanf("%d",&tc);
    while(tc--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        MEM(rd,0);
//        MEM(mp,0);
        for(int i=1;i<=n;i++)
            mp[i].clear();
        while(m--)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            mp[b].push_back(a);  rd[a]++;
        }

        priority_queue<int,vector<int>,cmp> q;
        for(int i=1;i<=n;i++)
            if(rd[i]==0)  q.push(i);
        int top=-1;
        while(!q.empty())
        {
            int tmp=q.top();
            q.pop();
            for(int i=0;i<mp[tmp].size();i++)
            {
                rd[mp[tmp][i]]--;
                if(rd[mp[tmp][i]]==0)
                    q.push(mp[tmp][i]);
            }
            ans[++top]=tmp;
        }

        printf("%d",ans[n-1]);
        for(int i=n-2;i>=0;i--)
            printf(" %d",ans[i]);
        puts("");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值