• UVA522 Schedule Problem


    • 题目分析

    题面很直白, 不难看出是个差分约束.

    这题的特点在于项目各个部分之间的先后关系.
    怎么处理呢? 拆点? 好像有点麻烦... 因为题目输入会给出各个部分的时间, 所以其实可以直接用边权表示这种约束.

    题目要求总时间最短, 所以应该把约束整理成 (d_x geq d_y + c) 的形式然后跑最长路.

    建图如下:

    Len[i]表示第 i 部分的时间
    
    Add(u, v, -Len[v]); //FAS
    Add(u, v, Len[u] - Len[v]); //FAF
    Add(u, v, Len[u]); //SAF
    Add(u, v, 0); //SAS
    

    关于无解情况, 就是 SPFA 找到了正环.
    另外注意输出格式, 每组输出间要有空行.

    • 代码

    #include <cstdio>
    #include <queue>
    #include <iostream>
    #include <string>
    #include <cstring>
    
    const int N = 1e5;
    const int M = 1e6;
    int Dis[N + 5], Head[N + 5], Len[N + 5], n, m;
    struct Edge {int To, Nxt, Val;} S[M + 5];
    int Cnt_Vis[N + 5], Cnt;
    bool Vis[N + 5];
    
    bool SPFA();
    void Add(int, int, int);
    
    int main() {
    	std::ios::sync_with_stdio(false);
    
    	int tap_Cnt = 0;
    	while(std::cin >> n) {
    		++tap_Cnt;
    		std::cout << "Case " << tap_Cnt << ":";
    		for(int i = 1; i <= n; i ++) std::cin >> Len[i];
    		while(true) {
    			int u, v;
    			std::string tap;
    			std::cin >> tap;
    			if(tap[0] == '#') break;
    			std::cin >> u >> v;
    			if(tap[0] == 'F' && tap[2] == 'S') Add(u, v, -Len[v]);
    			if(tap[0] == 'F' && tap[2] == 'F') Add(u, v, Len[u] - Len[v]);
    			if(tap[0] == 'S' && tap[2] == 'F') Add(u, v, Len[u]);
    			if(tap[0] == 'S' && tap[2] == 'S') Add(u, v, 0);
    		
    		} if(!SPFA()) std::cout << "
    impossible";
    		else for(int i = 1; i <= n; i ++) 
    			std::cout << "
    " << i << " " << Dis[i];
    		std::cout << "
    
    ";
    		memset(Head, 0, sizeof(Head)), Cnt = 0;
    	} return 0;
    
    } void Add(int u, int v, int w) {
        ++Cnt;
        Cnt[S].Val = w, Cnt[S].To = v;
        Cnt[S].Nxt = u[Head], u[Head] = Cnt;
        
    } bool SPFA() {
    	memset(Dis, 0, sizeof(Dis));
    	memset(Cnt_Vis, 0, sizeof(Vis));
    	memset(Vis, false, sizeof(Vis));
    
        std::queue<int> Q;
        for(int i = 1; i <= n; i ++) Q.push(i), Vis[i] = true, Cnt_Vis[i] = 1;
    
        while(Q.size()) {
            int tap = Q.front();
            Q.pop(), tap[Vis] = false;
            for(int i = tap[Head]; i; i = i[S].Nxt) {
                int v= i[S].To;
                if(v[Dis] < tap[Dis] + i[S].Val) {
                    v[Dis] = tap[Dis] + i[S].Val;
                    if(!v[Vis]) {
                        if((++v[Cnt_Vis]) >= n) return false;
                        v[Vis] = true, Q.push(v);
                    }
                }
            }
        } return true;
    }
    
  • 相关阅读:
    5.2 spring5源码--spring AOP源码分析三---切面源码分析
    5.2 spring5源码--spring AOP源码分析二--切面的配置方式
    在Dubbo中使用Zookeeper入门案例
    Dubbo直连方式改造
    Dubbo直连方式
    16.3.3 对矢量可执行的其它操作
    16.3.2 可对矢量(vector)执行的操作
    16.3 标准模板库
    16.2.2 有关智能指针的注意事项
    16.2.1 使用智能指针
  • 原文地址:https://www.cnblogs.com/Rothen/p/13851812.html
Copyright © 2020-2023  润新知