HDU4109 Instrction Arrangement【差分约束】【拓扑排序】

来源:互联网 发布:黑客网站源码 编辑:程序博客网 时间:2024/06/01 08:23

题意:机器同时可以进行多个任务,有些任务必须在某任务完成c分钟后才能开始。求完成这些任务最少时间


思路:d(v) - d(u) ≥ c,差分约束,这个问题能转化到最短路径问题。对于最短路径中的松弛操作,从a松弛b,对于连接到b的所有的边 d(b) ≤ d(a) + w(a,b),a -> b建边权为w。d(u) ≤ d(v) - c,v -> u,建 -c 的边,跑一个最短路,建一个起点和终点,把所有点和它们连一起。到终点有最后的任务也要运行1分钟,把边到终点的权设为-1,答案是 -d[en]


还有一种做法是拓扑排序,用入度为0的点去更新其他点的最大值。


#include<stdio.h>#include<iostream>#include<string.h>#include<string>#include<stdlib.h>#include<math.h>#include<vector>#include<list>#include<map>#include<stack>#include<queue>#include<algorithm>#include<numeric>#include<functional>using namespace std;typedef long long ll;const int maxn = 1005;int d[maxn],inq[maxn],dis[maxn][maxn];vector<int> v[maxn];void spfa(){queue<int> q;while(!q.empty())q.pop();memset(inq,0,sizeof inq);memset(d,0x3f,sizeof d);d[0] = 0;q.push(0);while(!q.empty()){int now = q.front();q.pop();inq[now] = 0;for(int i = 0; i < v[now].size(); i++){int temp = v[now][i];if(d[now]+dis[now][temp] < d[temp]){d[temp] = d[now]+dis[now][temp];if(!inq[temp]){inq[temp] = 1;q.push(temp);}}}}}int main(void){int n,m,i,j,k;while(scanf("%d%d",&n,&m)!=EOF){for(i = 0; i <= n+1; i++)v[i].clear();for(i = 0; i < m; i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);a++;b++;v[b].push_back(a);dis[b][a] = -c;}for(i = 1; i <= n; i++){v[0].push_back(i);dis[0][i] = 0;v[i].push_back(n+1);dis[i][n+1] = -1;}spfa();printf("%d\n",-d[n+1]);}return 0;}


#include<stdio.h>#include<iostream>#include<string.h>#include<string>#include<stdlib.h>#include<math.h>#include<vector>#include<list>#include<map>#include<stack>#include<queue>#include<algorithm>#include<numeric>#include<functional>using namespace std;typedef long long ll;const int maxn = 1005;int n;int counts[maxn],dis[maxn][maxn],d[maxn];vector<int> g[maxn];queue<int> q;void init(int n){    memset(counts,0,sizeof(counts));    for(int i=0;i<=n;i++)        g[i].clear();    while(!q.empty())        q.pop();}void add(int u,int v,int c){    g[u].push_back(v);    counts[v]++;    dis[u][v] = c;}bool topsort(){int sum = n+2;  //n 节点总数bool flag=false;memset(d,0,sizeof d);for(int i=0;i<n;i++)  //入度为0入栈{if(counts[i]==0)q.push(i);}while(!q.empty()){sum--;int j=q.front();q.pop();for(int k=0;k<g[j].size();k++){d[ g[j][k] ] = max(d[ g[j][k] ],d[j] + dis[j][ g[j][k] ]);if(--counts[g[j][k]]==0)q.push(g[j][k]);}}if(sum>0)return false;  //表明存在回路return true;        //OK}int main(void){int i,j,k,m;while(scanf("%d %d",&n,&m)!=EOF){init(n+1);while(m--){int a,b,c;scanf("%d %d %d",&a,&b,&c);a++,b++;add(a,b,c);}for(i = 1; i <= n; i++){add(0,i,0);add(i,n+1,1);}topsort();printf("%d\n",d[n+1]);}return 0;}



阅读全文
0 0