CF1472G Solution

题目链接

题解

⭐:DAG上的dp很可能需要多次转移,只得使用类SPFA而非Dijkstra算法

(d)数组Dijkstra预处理即可。然后建反向图,dp。

状态:(dp[i][j])表示第i个节点是否((j=1/0))已使用2操作时的答案。

转移方程:

[dp[v][0]=min(dp[v][0],dp[u][0]),dp[v][1]=min(dp[v][1],dp[u][1])quad (d_v<d_u)\ dp[v][1]=min(dp[v][1],dp[u][0])quad (d_vge d_u) ]

转移时在反图上以节点1为起点进行类SPFA的操作,因为转移后结果不一定全局最优,单个节点需要入队多次(好耶没有被卡)。

目标状态:(min(dp[i][0],dp[i][1]))

AC代码

#include<bits/stdc++.h>
#define mp make_pair
using namespace std;
const int N=2e5+10;
int fst[N],nxt[N],v[N],cnt;//原图
int fst2[N],nxt2[N],v2[N],cnt2;//反图
int dis[N],dp[N][2],n; //dis:题目中的d数组
bool vis[N];
priority_queue<pair<int,int> > q;
queue<int> q2;
void add(int x,int y)
{
	v[++cnt]=y;
	nxt[cnt]=fst[x],fst[x]=cnt;
}
void add2(int x,int y)
{
	v2[++cnt2]=y;
	nxt2[cnt2]=fst2[x],fst2[x]=cnt2;
}
void dij()
{
	for(int i=1;i<=n;i++) vis[i]=0,dis[i]=0x3f3f3f3f;
	dis[1]=0;
	q.push(mp(0,1));
	while(!q.empty())
	{
		int x=q.top().second; q.pop();
		if(vis[x]) continue;
		vis[x]=1;
		for(int i=fst[x];i;i=nxt[i])
		{
			int y=v[i];
			if(dis[y]>dis[x]+1) 
				{dis[y]=dis[x]+1; q.push(mp(-dis[y],y));}
		}
	}
}
void bfs()
{
	memset(vis,0,sizeof(vis));
	memset(dp,0x3f,sizeof(dp));
	for(int i=1;i<=n;i++) dp[i][0]=dis[i],vis[i]=1;
	for(int i=1;i<=n;i++) q2.push(i);
	while(!q2.empty())
	{
		int x=q2.front(); q2.pop();
		vis[x]=0;
		for(int i=fst2[x];i;i=nxt2[i])
		{
			int y=v2[i];
			if(dis[y]<dis[x])
			{
				if(dp[x][0]<dp[y][0])
				{
					dp[y][0]=dp[x][0];
					if(!vis[y]) {vis[y]=1; q2.push(y);}
				}
				if(dp[x][1]<dp[y][1])
				{
					dp[y][1]=dp[x][1];
					if(!vis[y]) {vis[y]=1; q2.push(y);}
				}
				continue;
			}
			if(dp[x][0]<dp[y][1])
			{
				dp[y][1]=dp[x][0];
				if(!vis[y]) {vis[y]=1; q2.push(y);}
			}
		}
	}
}
int main()
{
	int t,m,x,y;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		for(int i=0;i<=n;i++) fst[i]=fst2[i]=0;
		cnt=cnt2=0;
			for(int i=1;i<=m;i++) 
		{
			scanf("%d%d",&x,&y); 
			add(x,y),add2(y,x);
		}
		dij(); bfs();
		for(int i=1;i<=n;i++) printf("%d ",min(dp[i][0],dp[i][1]));
		printf("
");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/violetholmes/p/14638940.html