
本文共 2709 字,大约阅读时间需要 9 分钟。
拓扑排序(差分约束) - Reward - HDU 2647
题意:
格林剧团发工资的时候又到辣,格林剧团来到了圣巢,他们入乡随俗,将工资用圣巢的货币–吉欧来结算。格林团长决定每个人的最低工资是888吉欧,同时有些工人希望自己的工资要比其他某个人的高。格林团长希望在尽可能的少发工资的同时满足其他所有人的需求。请你帮帮格林团长吧,格林团长会邀请你与其在剧团内共舞一场猩红仪式。
Input
题目包含多组输入,第一行输入两个整数n,m,分别表示工人的数量与需求的个数。 接下来m行,每一行都包含两个整数a和b,表示a的工资必须比b的工资高
Output
对于每一组输入,输出格林团长最少花费的吉欧数量。如果格林团长不能满足所有人的需求,输出-1.
Sample Input
2 11 22 21 22 1
Sample Output
1777-1
分析:
差 分 约 束 问 题 。 差分约束问题。 差分约束问题。
若 A 要 求 比 B 高 , 即 要 求 A > B , 即 A ≥ B + 1 , 我 们 对 应 建 边 A − > B , 边 权 为 1 。 若A要求比B高,即要求A>B,即A≥B+1,我们对应建边A->B,边权为1。 若A要求比B高,即要求A>B,即A≥B+1,我们对应建边A−>B,边权为1。
最 终 要 求 最 小 值 , 跑 最 长 路 。 最终要求最小值,跑最长路。 最终要求最小值,跑最长路。
由 于 边 权 恒 大 于 0 , 故 我 们 可 以 用 拓 扑 排 序 求 最 短 路 , 时 间 复 杂 度 为 O ( n + m ) 。 由于边权恒大于0,故我们可以用拓扑排序求最短路,时间复杂度为O(n+m)。 由于边权恒大于0,故我们可以用拓扑排序求最短路,时间复杂度为O(n+m)。
若 存 在 正 环 或 孤 立 点 , 拓 扑 排 序 得 到 的 元 素 数 量 将 会 小 于 n 。 若存在正环或孤立点,拓扑排序得到的元素数量将会小于n。 若存在正环或孤立点,拓扑排序得到的元素数量将会小于n。 以 此 来 判 断 是 否 有 解 。 以此来判断是否有解。 以此来判断是否有解。
若 有 解 , 由 于 要 求 所 有 人 薪 水 不 低 于 888 , 即 对 任 意 的 i , d i s [ i ] ≥ 0 + 888 , 若有解,由于要求所有人薪水不低于888,即对任意的i,dis[i]≥0+888, 若有解,由于要求所有人薪水不低于888,即对任意的i,dis[i]≥0+888,
我 们 可 以 建 立 虚 拟 源 点 0 号 点 , d i s [ 0 ] = 0 , 且 0 号 点 与 其 他 点 之 间 均 建 立 一 条 边 权 为 888 的 边 。 我们可以建立虚拟源点0号点,dis[0]=0,且0号点与其他点之间均建立一条边权为888的边。 我们可以建立虚拟源点0号点,dis[0]=0,且0号点与其他点之间均建立一条边权为888的边。
等 价 于 我 们 直 接 初 始 化 d i s 数 组 为 888 , 这 样 可 以 省 掉 建 立 虚 拟 源 点 的 过 程 。 等价于我们直接初始化dis数组为888,这样可以省掉建立虚拟源点的过程。 等价于我们直接初始化dis数组为888,这样可以省掉建立虚拟源点的过程。
接 着 按 照 阶 段 跑 最 长 路 即 可 。 接着按照阶段跑最长路即可。 接着按照阶段跑最长路即可。
代码:
#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int N=10010, M=20010;int n,m;int e[M],ne[M],h[N],idx;int dis[N];int d[N];int q[N],hh,tt=-1;void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++;}bool topsort(){ hh=0,tt=-1; for(int i=1;i<=n;i++) if(!d[i]) q[++tt]=i; while(hh<=tt) { int u=q[hh++]; for(int i=h[u];~i;i=ne[i]) { int j=e[i]; d[j]--; if(!d[j]) q[++tt]=j; } } return tt==n-1;} int cal(){ for(int i=1;i<=n;i++) dis[i]=888; //初始值 for(int i=0;i<n;i++) //遍历拓扑序,跑最长路 { int u=q[i]; for(int j=h[u];~j;j=ne[j]) { int k=e[j]; dis[k]=max(dis[k],dis[u]+1); } } int res=0; for(int i=1;i<=n;i++) res+=dis[i]; return res;}int main(){ while(~scanf("%d%d",&n,&m)) { idx=0; memset(h,-1,sizeof h); memset(d,0,sizeof d); int a,b; while(m--) { scanf("%d%d",&a,&b); add(b,a); d[a]++; } if(!topsort()) puts("-1"); else printf("%d\n",cal()); } return 0;}
发表评论
最新留言
关于作者
