hdu 4857(拓扑)

这题读完,马上想到是拓扑,但裸拓扑果断wa了。在仔细分析一下,应该加个优先队列,结果又wa了。没办法,参考了下大牛。原来还要拓扑的反向建边。先说拓扑。

拓扑的作用就是排列一组相互有前后关系的数据的算法。最经典的例子就是课程安排。如果让你给一个班级安排课程,有识字,组词,造句,写文章,小学数学。你要如何安排呢?如果是我,果断就是刚才的顺序,先识字,在组词,造句,最后写文章,至于数学,放哪里都行。你在无形中就用到了拓扑排序。拓扑就是本着一些东西必须在另一些东西之前的原则排序的。你不可能还没识字,就让写文章吧。这个算法放到本题,真是太贴切了。下面就介绍一下拓扑的算法思路。介绍之前,必须说一下入度这个名词。所谓入度就是......还是先贴张图再说吧。


画的丑,能说明问题就行。看上图,1的入度0,2的入度2,3的入度0,4的入度1.好了感觉不需要再解释了。

明白入度后就简单了。拓扑的思路就是每次取出入度为0的点,然后把与它相连的点的入度减一,就这样循环,直到所有的点都被取出。像上面的图。第一次取1或3。假设我们取1

则删去1点,1点与2点相连,把2点的入度减一。此时,再取入度为0的点,只能是3了。2与3连,再把2的入度减一,此时2的入度就为0,取出2,4与2相连,4的入度减一,此时4的入度为0,再取出4,结束。保存数据时,可以用个二维数组,第一维代表操作点,第二维代表与操作点相连的点。入度则用一个一维数组保存即可。核心代码

<span style="font-size:18px;">for(int i=1;i<n;i++)
{
	cin>>a>>b;
	if(!arr[a][b])//防重复,比如数据为1,2  1,2 
	{
		arr[a][b]=1;
		rd[b]++;//入度 
	}
}</span>
下面介绍一下优先队列,这个不需要过多解释,只给出几种实现形式就够了。

1 c++默认

priority_queue<int> q;默认是按优先级从大到小排列。

2  自定义优先级

struct cmp
{


operator bool ()(int x, int y)


{
return x > y; // x小的优先级高


//也可以写成其他方式,如: return p[x] > p[y];表示p[i]小的优先级高
}
};


priority_queue<int, vector<int>, cmp>q;//定义方法

3  结构体形式

struct node
{
int x, y;


friend bool operator < (node a, node b)
{
return a.x > b.x; //结构体中,x小的优先级高
}
};


priority_queue<node>q;//定义方法


//在该结构中,y为值, x为优先级。

当这些东西懂清楚以后,这题就是1+1了。就是2者结合就行了。上本题代码

<span style="font-size:18px;">#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
int rd[30005];
int queu[30005];
vector<int> a[30005];
int n,m;
struct cmp
{
	bool operator () (const int &a,const int &b)
	{
		return a<b;
	}	
};
priority_queue<int,vector<int>,cmp> q;
void topo()
{
	for(int i=1;i<=n;i++)
	{
		if(rd[i]==0)
		{
			q.push(i);
		}
			
	}
	int count=1;
	while(!q.empty())
	{
		int x=q.top();
		q.pop();
		for(int i=0;i<a[x].size();i++)
		{
			rd[a[x][i]]--;
			if(rd[a[x][i]]==0)
			{
				q.push(a[x][i]);
			}
				
		}
		queu[count++]=x;
	}
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		for(int i=0;i<=n;i++)
		{
			rd[i]=0;
			a[i].clear();
		}
		int x,y;
		while(m--)
		{
			scanf("%d%d",&x,&y);
			a[y].push_back(x);
			rd[x]++;<span style="font-family: 'Microsoft YaHei', lucida, verdana, sans-serif;">//这里就是反向建边,仔细看就so easy。</span>

		}
		topo();
		for(int i=n;i>0;i--)
		{
			if(i!=1)
				cout<<queu[i]<<" ";
			else
				cout<<queu[i]<<endl;
		}
	}
	return 0;
}</span>



乐播投屏是一款简单好用、功能强大的专业投屏软件,支持手机投屏电视、手机投电脑、电脑投电视等多种投屏方式。 多端兼容与跨网投屏:支持手机、平板、电脑等多种设备之间的自由组合投屏,且无需连接 WiFi,通过跨屏技术打破网络限制,扫一扫即可投屏。 广泛的应用支持:支持 10000+APP 投屏,包括综合视频、网盘与浏览器、美韩剧、斗鱼、虎牙等直播平台,还能将央视、湖南卫视等各大卫视的直播内容一键投屏。 高清流畅投屏体验:腾讯独家智能音画调校技术,支持 4K 高清画质、240Hz 超高帧率,低延迟不卡顿,能为用户提供更高清、流畅的视觉享受。 会议办公功能强大:拥有全球唯一的 “超级投屏空间”,扫码即投,无需安装。支持多人共享投屏、远程协作批注,PPT、Excel、视频等文件都能流畅展示,还具备企业级安全加密,保障会议资料不泄露。 多人互动功能:支持多人投屏,邀请好友加入投屏互动,远程也可加入。同时具备一屏多显、语音互动功能,支持多人连麦,实时语音交流。 文件支持全面:支持 PPT、PDF、Word、Excel 等办公文件,以及视频、图片等多种类型文件的投屏,还支持网盘直投,无需下载和转格式。 特色功能丰富:投屏时可同步录制投屏画面,部分版本还支持通过触控屏或电视端外接鼠标反控电脑,以及在投屏过程中用画笔实时标注等功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值