https://www.luogu.org/problem/show?pid=1260
题目描述
造一幢大楼是一项艰巨的工程,它是由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
说明
由@zhouyonglong提供SPJ
差分约束、现学现做。。。
SPFA松弛:
1 #include <cstring> 2 #include <cstdio> 3 #include <queue> 4 5 const int N(11110); 6 int n,m,sumedge,head[N]; 7 struct Edge 8 { 9 int v,w,next; 10 Edge(int v=0,int next=0,int w=0): 11 v(v),next(next),w(w){} 12 }edge[52330]; 13 inline void ins(int u,int v,int w) 14 { 15 edge[++sumedge]=Edge(v,head[u],w); 16 head[u]=sumedge; 17 } 18 19 int dis[N]; 20 bool vis[N]; 21 bool SPFA(int u) 22 { 23 vis[u]=1; 24 for(int v,i=head[u];i;i=edge[i].next) 25 { 26 v=edge[i].v; 27 if(dis[v]>dis[u]+edge[i].w) 28 { 29 dis[v]=dis[u]+edge[i].w; 30 if(!vis[v]) 31 { 32 if(!SPFA(v)) return 0; 33 } 34 else return 0; 35 } 36 } 37 vis[u]=0; 38 return 1; 39 } 40 41 #define min(a,b) (a<b?a:b) 42 int AC() 43 { 44 scanf("%d%d",&n,&m); 45 for(int u,v,w,i=1;i<=m;i++) 46 scanf("%d%d%d",&u,&v,&w),ins(v,u,w); 47 for(int i=1;i<=n;i++) ins(0,i,0); 48 memset(dis,127/3,sizeof(dis)); dis[0]=0; 49 if(!SPFA(0)) 50 { 51 printf("NO SOLUTION"); 52 return 0; 53 } 54 int lose=0x7fffffff; 55 for(int i=1;i<=n;i++) lose=min(lose,dis[i]); 56 for(int i=1;i<=n;i++) printf("%d\n",dis[i]-lose); 57 } 58 59 int Hope=AC(); 60 int main(){;}
暴力松弛
1 #include <cstdio> 2 3 int n,m,dis[12120]; 4 struct Edge 5 { 6 int u,v,w; 7 }road[52332]; 8 9 #define min(a,b) (a<b?a:b) 10 int AC() 11 { 12 scanf("%d%d",&n,&m); 13 for(int u,v,w,i=1;i<=m;i++) 14 scanf("%d%d%d",&road[i].v,&road[i].u,&road[i].w); 15 for(int i=1;i<n;i++) 16 for(int j=1;j<=m;j++) 17 dis[road[j].v]=min(dis[road[j].v],dis[road[j].u]+road[j].w); 18 for(int i=1;i<=m;i++) 19 if(dis[road[i].v]>dis[road[i].u]+road[i].w) 20 { 21 printf("NO SOLUTION"); 22 return 0; 23 } 24 int lose=0x7fffffff; 25 for(int i=1;i<=n;i++) lose=min(lose,dis[i]); 26 for(int i=1;i<=n;i++) printf("%d\n",dis[i]-lose); 27 return 0; 28 } 29 30 int Hope=AC(); 31 int main(){;}
时间: 2024-10-10 04:07:57