zoukankan      html  css  js  c++  java
  • 洛谷 P1260 工程规划(差分约束)

    题目描述

    造一幢大楼是一项艰巨的工程,它是由n个子任务构成的,给它们分别编号1,2,…,n(5≤n≤1000)。由于对一些任务的起始条件有着严格的限制,所以每个任务的起始时间T1,T2,…,Tn并不是很容易确定的(但这些起始时间都是非负整数,因为它们必须在整个工程开始后启动)。例如:挖掘完成后,紧接着就要打地基;但是混凝土浇筑完成后,却要等待一段时间再去掉模板。

    这种要求就可以用M(5≤m≤5000)个不等式表示,不等式形如Ti-Tj≤b代表i和j的起始时间必须满足的条件。每个不等式的右边都是一个常数b,这些常数可能不相同,但是它们都在区间(-100,100)内。

    你的任务就是写一个程序,给定像上面那样的不等式,找出一种可能的起始时间序列T1,T2,…,Tn,或者判断问题无解。对于有解的情况,要使最早进行的那个任务和整个工程的起始时间相同,也就是说,T1,T2,…,Tn中至少有一个为0。

    输入输出格式

    输入格式:

    第一行是用空格隔开的两个正整数n和m,下面的m行每行有三个用空格隔开的整数i,j,b对应着不等式Ti-Tj≤b。

    输出格式:

    如果有可行的方案,那么输出N行,每行都有一个非负整数且至少有一个为0,按顺序表示每个任务的起始时间。如果没有可行的方案,就输出信息“NO SOLUTION”。

    输入输出样例

    输入样例#1: 
    5 8
    1 2 0
    1 5 -1
    2 5 1
    3 1 5
    4 1 4
    4 3 -1
    5 3 -1
    5 4 -3
    输出样例#1: 
    0
    2
    5
    4
    1
    
    输入样例#2: 
    5 5
    1 2 -3
    1 5 -1
    2 5 -1
    5 1 -5
    4 1 4
    输出样例#2: 
    NO SOLUTION

    解:这道题目我们首先需要判负环,如果中间存在负环,那么我们就输出"NO SOLUTION";

      那么接下来我们可以建一个“超级原点”,使它连接所有的点,这样即使原本多个联通块,我们也可以一次搜完所有的联通块了。

      因为题目中要求至少一个0,那么我们只需要对每个点的距离减去最小距离的点的值,就能保证至少有一个0(就是最小距离的点)了。

    #include<bits/stdc++.h>
    using namespace std;
    #define man 5050
    template <class T>
    inline void read(T &x)
    {	x=0;bool f=0;char ch=getchar();
    	while(!isdigit(ch)){	f=(ch==45);ch=getchar();}
    	while(isdigit(ch)) {	x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	x=f?(~x+1):x;
    	}
    #define ll long long
    /*TEST*/
    int n,m;
    /*EDGE*/
    int degree[man],head[man<<2],num=0;
    struct edge
    {	int from,next,to,dis;}e[man<<2];
    inline void add(int from,int to,int dis)
    {	e[++num].next=head[from];
    	e[num].to=to;
    	e[num].dis=dis;
    	e[num].from=from;
    	head[from]=num;
    	}
    /*TOPSORT*/
    int dis[man];
    bool vis[man],flag=0;
    int cnt[man]={0};
    inline int spfa(int s)
    {
    
        queue<int >q;
        q.push(s);dis[s]=0;vis[s]=1;
        do
        {
            int u=q.front();q.pop();
            vis[u]=0;
            for(int i=head[u];i;i=e[i].next)
            {
                ll to=e[i].to;
                if(dis[to]>dis[u]+e[i].dis)
                {	dis[to]=dis[u]+e[i].dis;
                    if(!vis[to])
                    {
                        q.push(to);
                        vis[to]=1;
                        cnt[to]++;
                        }
                    if(cnt[to]>n) return 1;
                    }			
                }
            }while(q.size());
        return 0;
        }
    int main()
    {	read(n);read(m);
    	for(int i=1;i<=m;i++)
    	{	int x,y,z;
    		read(x);read(y);read(z);
    		add(y,x,z);
    		}
    	for(int i=1;i<=n;i++)
    	    add(0,i,0);
    	memset(vis,0,sizeof(vis));
        memset(dis,0x7f,sizeof(dis));
    	if(spfa(0)==1) {printf("NO SOLUTION
    ");return 0;}
    	int minn=2000000000;
    	for(int i=1;i<=n;i++)
    	    minn=min(minn,dis[i]);
    	for(int i=1;i<=n;i++)
    	    printf("%d
    ",dis[i]-minn);
    	return 0;
    	}
    

      

  • 相关阅读:
    [Silverlight]常见问题
    [C#]有趣的VS扩展DebuggerVisualizer
    [EF5.0CODE FIRST]多对一及自关联映射的处理
    自定义控件传值
    关于.Net中类型转换ToInt32
    SQL版整数转IP
    SQL2008 Merge关键字用法与简例
    SQL语句,同时返回结果集,输出参数的值及return值
    多线程与异步操作实现的探讨
    SQL Prompt4 破解版
  • 原文地址:https://www.cnblogs.com/Slager-Z/p/7800866.html
Copyright © 2011-2022 走看看