• 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;
    }
    
  • 相关阅读:
    sql语句中in和exists的区别
    springboot整合kafka
    多线程基础(三)线程通信
    多线程基础(四)线程控制
    多线程基础(二)线程状态
    创建计算字段
    MySQL学习之正则表达式篇
    response没有实现跳转,而是提示浏览器下载文件
    AJAX简述
    四大作用域
  • 原文地址:https://www.cnblogs.com/violetholmes/p/14638940.html
Copyright © 2020-2023  润新知