【拓扑排序】威虎山的分配


思路

首先是对题意的分析。

因为它说a要比b多,给你很多这样的条件语句,就想到需要构建图,让小的指向大的,而且按照题意不会出现“环”(不是≥而一定是>),这样就可以用拓扑排序成线性序列,就可以挨个分配钱了

我想了下,如果条件是“≥”还能不能用拓扑排序,答案应该是不能,因为很可能出现“环”,而拓扑排序的前提就是“无环有向图”,如果有环的话,拓扑排序得到的线性序列是没有涵盖所有点的。因为环上每个点的入度都不为0,并未入队(见图理解),那你那些环上的点与后面其他点的条件也不能得到考虑:


这也就是为什么对于这道题,最后判断合法与否就是看入队的个数是否<总个数n,如果是,则说明无解,该图是有环的,而此题中有环是不允许的,不然不符合现实。


代码

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e4+5;
const int MAXM=2e4+5;
struct edge
{
	int u,v,next;
}e[MAXN]; 
int p[MAXM];
int vis=0;
int rudu[MAXN];
int money[MAXN];
int n;
void init()
{
	memset(p,-1,sizeof(p));
	memset(rudu,0,sizeof(rudu));
	for(int i=1;i<=n;i++)
		money[i]=100;
}
int cnt=1;
void insert(int u,int v)
{
	e[cnt].v=v;
	e[cnt].next=p[u];
	p[u]=cnt;
	rudu[v]++;
	cnt++;
}
void topo()
{
	queue<int> q;
	//先将入度为0的结点入队 
	for(int i=1;i<=n;i++)
	{
		if(rudu[i]==0)
		{
			q.push(i);
			vis++;
		}	
	}
	while(q.empty()==false)
	{
		int a=q.front();
		q.pop();
		for(int i=p[a];i!=-1;i=e[i].next)
		{
			int v=e[i].v;
			rudu[v]--;
			money[v]=money[a]+1;
			if(rudu[v]==0)
			{
				q.push(v);
				vis++;
			}
		}
	}
}

int main()
{
	int m;
	cin>>n>>m;
	init();
	while(m--)
	{
		int a,b;
		cin>>a>>b;
		insert(b,a);
	}
	topo();
	if(vis<n) 
	{
		cout<<"Unhappy!";
		return 0;
	}
	int ans=0;
	for(int i=1;i<=n;i++)
		ans+=money[i];
	cout<<ans;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值