首页 > 代码库 > HDU2647(拓扑排序+反向建图)

HDU2647(拓扑排序+反向建图)

题意不说了,说下思路。

给出的关系是a要求的工资要比b的工资多,由于尽可能的让老板少付钱,那么a的工资就是b的工资+1,可以确定关系为a>b,根据拓扑排序建边的原则是把“小于”关系看成有向边,那么我们可以建边v->u。

#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
#include <math.h>
#include <map>
#include <queue>
#include <stack>
#include <set>
#define M 10000+5
#define LL long long
#define Ld __int64
#define eps 0.00001
#define INF 999999999
#define MOD 112233
#define MAX 26
#define PI acos(-1.0)
using namespace std;

vector<int> G[M];
int num[M];
int n;
int into[M],ans;

int toposort()
{
	queue<int> q;
	int cnt=0;
	ans=0;
	for(int i=1;i<=n;i++)
	{
		if(into[i]==0)						//入度为0的点进入队列中
			q.push(i);
	}
	while(!q.empty())
	{
		cnt++;
		int u=q.front();
		ans+=num[u];
		q.pop();
		for(int i=0;i<G[u].size();i++)
		{
			int v=G[u][i];
			if(--into[v]==0)				//若删除(u,v)这条边之后,v的入度也为0,则压入队列中
			{
				q.push(v);				
				num[v]=num[u]+1;			//v要求的工资比u高
			}
		}
	}
	if(cnt!=n)					//判断有无环,-1表示有环,1表示无环
		ans=-1;
	return ans;
}

int main()
{
	int m;
	while(~scanf("%d%d",&n,&m))
	{
		for(int i=0;i<=n;i++)
		{
			G[i].clear();
			into[i]=0;
			num[i]=888;
		}
		while(m--)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			G[v].push_back(u);
			into[u]++;
		}
		printf("%d\n",toposort());
	}
	return 0;
}


/*

5 4
2 1
2 5
5 3
3 4


*/