这题首先要明确输出什么——–输出从1-N编号的球的重量,并且尽可能使1号球轻,如果1号轻一样重,则输出2号球尽可能轻的方案,…以此类推.
如果按照正常的思路,就是拓扑排序,每次取出最小的编号,使其重量为当前最小。但是这样存在一个问题,就是:当前最小的编号的球不一定是能够最先接近1球,有可能当前编号最大的那个或者其他球最先接近1号球。所以正向就不能够得到正确的答案。可以这样想:每次我都将编号最大的、离1号球最远的那个球,使其重量为当前重量的最大值,那么1号球最终的剩下的选择肯定就是最轻的了!
因此我们可以这样做:如何使远离1号或者小编号的大编号球重量取得最大值呢?用优先队列,每次取出最大的编号,使其重量为最大值(这样保证了小编号的球重量比较轻)。同时反向建图,因为输入中的右边是比较重的球,由于我们是要先给重的球赋重量,所以就要反向建图。
代码如下:
/*************************************************************************
> File Name: main.cpp
> Author:Eagles
> Mail:None
> Created Time: 2018年09月16日 星期日 10时27分28秒
> Description:POJ3687,拓扑排序
************************************************************************/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
#define N 1000
struct node
{
int to;
int nex;
}E[N*N];
int head[N];
int in_deg[N];
priority_queue<int, vector<int>, less<int> >q;
int cnt,num,n,m;
int ans[N];
bool flag;
bool addEdge(int a, int b)
{
for (int i=head[a]; i!=-1; i=E[i].nex)
{
if (E[i].to==b)
return false;
}
E[cnt].to=b;
E[cnt].nex=head[a];
head[a]=cnt++;
return true;
}
void init()
{
memset(head,-1,sizeof(head));
memset(in_deg,0,sizeof(in_deg));
num=cnt=0;
flag=true;
while (!q.empty())
q.pop();
scanf("%d%d",&n,&m);
for (int i=0; i<m; i++)
{
int a,b;
scanf("%d%d",&a,&b);
if (a==b)
flag=false;
if (addEdge(b,a))
in_deg[a]++;
}
}
void toposort()
{
for (int i=n ;i>0; i--)
{
if (in_deg[i]==0)
q.push(i);
}
int sum=n;
while (!q.empty())
{
int t=q.top();
q.pop();
ans[t]=sum--;
for (int i=head[t]; i!=-1; i=E[i].nex)
{
in_deg[E[i].to]--;
if (in_deg[E[i].to]==0)
q.push(E[i].to);
}
}
if (sum>0)
flag=false;
}
void get_ans()
{
if (flag)
{
for (int i=1; i<=n; i++)
{
printf("%d ",ans[i]);
}
printf("\n");
}
else
printf("-1\n");
}
void print()
{
printf("\n");
for (int i=1; i<=n; i++)
{
for (int j=head[i]; j!=-1; j=E[j].nex)
{
printf("%d %d\n",i,E[j].to);
}
}
}
int main()
{
int t;
while (~scanf("%d",&t))
{
while (t--)
{
init();
toposort();
get_ans();
}
}
return 0;
}
所以,在这里,优先队列的作用是:取得大编号球;反向建图的作用是:使重的球进入队列。二者合作,即可取得大编号的重球,剩下的自然就是小编号的轻球啦!