• Invade the Mars


    题目

    网上大把

    分析

    显然不能简单直接最短路
    城市被攻占的特点是:保护的城市都被攻占了
    那么这个城市被攻占的最早时间必然是所有保护他的城市中最大的被攻占时间
    于是我们可以
    (dis) 表示军队走到城市 (i) 驻扎于城外的最短时间
    (f) 表示所有保护他的城市中最大的被攻占时间
    最短路中,对于当前点 (u)
    先让他保护的点 (v) 度数--,并取 (f_v = max{dis_u})
    若度数降至 (0),可松弛并将其入队
    然后再考虑有向边的松弛
    具体可见代码

    (Code)

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    
    const int N = 3005 , M = 70005 , INF = 2e9;
    int T , n , m , tot , h[N] , dis[N] , vis[N] , deg[N] , f[N];
    vector<int> pt[N];
    
    struct edge{int nxt , to , w;}e[2 * M];
    struct node{
    	int id , d;
    	bool operator < (node c) const {return d > c.d;}
    };
    priority_queue<node> Q;
    
    inline void add(int x , int y , int z)
    {
    	e[++tot] = edge{h[x] , y , z} , h[x] = tot;
    }
    
    void dijkstra()
    {
    	memset(vis , 0 , sizeof vis);
    	while (!Q.empty()) Q.pop();
    	for(register int i = 1; i <= n; i++) dis[i] = INF , f[i] = 0;
    	Q.push(node{1 , dis[1] = 0});
    	node now;
    	while (!Q.empty())
    	{
    		now = Q.top() , Q.pop();
    		int id = now.id , v;
    		if (vis[id]) continue;
    		vis[id] = 1;
    		for(register int i = 0; i < pt[id].size(); i++)
    		{
    			v = pt[id][i];
    			f[v] = max(f[v] , dis[id]);
    			--deg[v];
    			if (deg[v] == 0 && dis[v] != INF)
    				dis[v] = max(dis[v] , f[v]) , Q.push(node{v , dis[v]});
    		}
    		for(register int i = h[id]; i; i = e[i].nxt)
    		{
    			v = e[i].to;
    			if (dis[id] + e[i].w < dis[v])
    			{
    				dis[v] = max(dis[id] + e[i].w , f[v]);
    				if (deg[v] == 0) Q.push(node{v , dis[v]});
    			}
    		}
    	}
    	printf("%d
    " , dis[n]);
    }
    
    int main()
    {
    	scanf("%d" , &T);
    	while (T--)
    	{
    		scanf("%d%d" , &n , &m);
    		for(register int i = 1; i <= n; i++) pt[i].clear() , deg[i] = 0;
    		tot = 0;
    		memset(h , 0 , sizeof h);
    		int x , y , z;
    		for(register int i = 1; i <= m; i++)
    			scanf("%d%d%d" , &x , &y , &z) , add(x , y , z);
    		for(register int i = 1; i <= n; i++)
    		{
    			scanf("%d" , &x) , deg[i] = x;
    			for(register int j = 1; j <= x; j++)
    				scanf("%d" , &y) , pt[y].push_back(i);
    		}
    		dijkstra();
    	}
    }
    
  • 相关阅读:
    C#设计模式之订阅发布模式
    ASP.NET Core依赖注入(DI)
    ASP.NET 开源导入导出库Magicodes.IE 完成Csv导入导出
    .NET IoC模式依赖反转(DIP)、控制反转(Ioc)、依赖注入(DI)
    曾经优秀的人,怎么就突然不优秀了?
    IDEA中文注释难看的简单解决办法
    JasperReport报表中输出Excel时,部分列不显示的问题
    为什么Spring Security看不见登录失败或者注销的提示
    JQuery文件上传插件JQuery.upload.js的用法简介
    一个很酷炫也挺实用的JS库leader-line
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/13819372.html
Copyright © 2020-2023  润新知