HDU2647 Reward (拓扑排序、反向建图)

家住魔仙堡 提交于 2020-03-04 00:00:55

Reward

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 16933    Accepted Submission(s): 5431

Problem Description
Dandelion's uncle is a boss of a factory. As the spring festival is coming , he wants to distribute rewards to his workers. Now he has a trouble about how to distribute the rewards.
The workers will compare their rewards ,and some one may have demands of the distributing of rewards ,just like a's reward should more than b's.Dandelion's unclue wants to fulfill all the demands, of course ,he wants to use the least money.Every work's reward will be at least 888 , because it's a lucky number.
 
Input
One line with two integers n and m ,stands for the number of works and the number of demands .(n<=10000,m<=20000)
then m lines ,each line contains two integers a and b ,stands for a's reward should be more than b's.
 
Output
For every case ,print the least money dandelion 's uncle needs to distribute .If it's impossible to fulfill all the works' demands ,print -1.
 
Sample Input
2 1 1 2 2 2 1 2 2 1
 
Sample Output
1777 -1
 

题目大意与分析

公司有N个员工,M个鄙视关系,对于每一对关系(a,b),a都希望工资比b高,最低工资是888,求满足所有鄙视关系的最低工资总和,不能满足所有鄙视关系则输出-1
和一般的拓扑排序不同的是本题需要反向建图,因为如果正向建图,虽然能满足鄙视关系,但是没法保证工资的总数是最少的,具体的画图就可以明白了。
在bfs的时候,将当前此人处于鄙视链的第几层一起入队,这样可以实现层数的传递,方便求和。
#include<bits/stdc++.h>
using namespace std;

int anss,cnt,vis[10005],into[10005],n,m,x,y;
queue <int>q;
vector<int>mp[10005];

void bfs()
{
    while(!q.empty())
    {
        int now=q.front();    //当前的员工
        q.pop();   
        int step=q.front();   //当前的鄙视链层数
        q.pop();
        anss+=888+step;
        for(int i=0;i<mp[now].size();i++)
        {
            int next=mp[now][i];
            into[next]--;
            if(into[next]==0&&vis[next]==0)
            {
                q.push(next);
                q.push(step+1);
                cnt++;
                vis[next]=1;
            }
        }
    }
}

int main()
{
    while(cin>>n>>m)
    {
        memset(mp,0,sizeof(mp));
        memset(vis,0,sizeof(vis));
        memset(into,0,sizeof(into));
        cnt=0;
        anss=0;
        while(m--)
        {
            cin>>x>>y;
            mp[y].push_back(x);
            into[x]++;
        }
        for(int i=1;i<=n;i++)
        {
            if(into[i]==0)
            {
                q.push(i);
                q.push(0);
                cnt++;
                vis[i]=1;
            }
        }
        bfs();
        if(cnt==n)
            cout<<anss<<endl;
        else
            cout<<-1<<endl;
    }
}

 

 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!