省选专练 [POI2014]RAJ-Rally

又是一道神仙题

太神仙了

第一步:考虑这是有向无环图,故思考TopSort????我真是想不到

由于这是有向无环图

定义F(i)为到达i的最长路径

G(i)为从i出发的最长路径

故:F(u)+G(v)+1为最长链

用一个可删除堆优化一下就好了

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+100;
inline void read(int &x){
	x=0;
	int f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
struct Front_star{
	int u,v,w,nxt;
}e[N*3*2];
int cnt=0;
int firstS[N]={};
int firstT[N]={};
void add(int u,int v,int *first){
	cnt++;
	e[cnt].u=u;
	e[cnt].v=v;
	e[cnt].nxt=first[u];
	first[u]=cnt;
}
int F[N]={};
int G[N]={};
int D[N]={};
int Q[N]={};
int head=0;
int tail=0;
int n,m;
struct Priority_Queue{
	priority_queue<int> Ins,Del;
	void Insert(int x){
		Ins.push(x);
	}
	void Delete(int x){
		Del.push(x);
	}
	int Top(){
		while(Del.size()&&Ins.size()&&Del.top()==Ins.top()){
			Del.pop();
			Ins.pop();
		}
		return Ins.top();
	}
}Que;
int main(){
	freopen("P3573.in","r",stdin);
	read(n);
	read(m);
	for(int i=1;i<=m;i++){
		int u,v;
		read(u);
		read(v);
		add(u,v,firstS);
		add(v,u,firstT);
		D[v]++;
	}
	for(int i=1;i<=n;i++){
		if(!D[i])Q[++tail]=i;
	}
	while(head!=tail){
		int x=Q[++head];
		for(int i=firstS[x];i;i=e[i].nxt){
			int v=e[i].v;
			if(!--D[v])Q[++tail]=v;
		}
	}
	for(int i=1;i<=n;i++){
		F[i]=G[i]=1;
	}
	for(int i=1;i<=n;i++){
		int x=Q[i];
		for(int i=firstS[x];i;i=e[i].nxt){
			int v=e[i].v;
			F[v]=max(F[v],F[x]+1);
		}
	}
	for(int i=n;i>=1;i--){
		int x=Q[i];
		for(int i=firstT[x];i;i=e[i].nxt){
			int v=e[i].v;
			G[v]=max(G[v],G[x]+1);
		}
	}
	int ans=1e9,pos;
	for(int i=1;i<=n;i++){
		Que.Insert(G[i]);
	}
	for(int i=1;i<=n;i++){
		int x=Q[i];
		for(int j=firstT[x];j;j=e[j].nxt){
			int v=e[j].v;
			Que.Delete(F[v]+G[x]);
		}
		Que.Delete(G[x]);
//		cout<<i<<" "<<Que.Top()<<'\n';
		if(ans>Que.Top()){
			ans=Que.Top();
			pos=x;
		}
		for(int j=firstS[x];j;j=e[j].nxt){
			int v=e[j].v;
			Que.Insert(F[x]+G[v]);
		}
		Que.Insert(F[x]);
	}
	cout<<pos<<" "<<ans-1;
}

转载于:https://www.cnblogs.com/Leo-JAM/p/10079204.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值