[bzoj3436]小K的农场_差分约束
小K的农场 bzoj-3436
题目大意:给定n个点,每个节点有一个未知权值。现在有m个限制条件,形如:点i比点j至少大c,点i比点j至多大c或点i和点j相等。问是否可以通过给所有点赋值满足所有限制条件。
注释:$1\le n,m\le 10^4$。
想法:差分约束裸题。
我们将限制条件转化一下:
$val_i-val_j>c$
$\Leftrightarrow val_i>val_j+c$;
我们就从j到i连一条权值为c的边。
$val_i-val_j<c$
$\Leftrightarrow val_j>val_i-c$;
我们就从i到j连一条权值为-c的边。
相等的话直接连两条权值为0的边
跑spfa求最长路,判断有没有正环即可。
最后,附上丑陋的代码... ...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define N 10010 using namespace std; queue< int >q; int n,m; int to[N<<2],nxt[N<<2],val[N<<2],head[N<<1],tot; int dis[N],tim[N]; bool vis[N]; inline char nc() { static char *p1,*p2,buf[100000]; return (p1==p2)&&(p2=(p1=buf)+ fread (buf,1,100000,stdin),p1==p2)?EOF:*p1++;} int rd() { int x=0; char c=nc(); while (! isdigit (c)) c=nc(); while ( isdigit (c)) x=(x<<3)+(x<<1)+(c^48),c=nc(); return x;} inline void add( int x, int y, int z) {to[++tot]=y; val[tot]=z; nxt[tot]=head[x]; head[x]=tot;} bool spfa() { while (!q.empty()) q.pop(); memset (dis,0x3f, sizeof dis); dis[0]=0; q.push(0); vis[0]= true ; while (!q.empty()) { int x=q.front(); q.pop(); vis[x]= false ; for ( int i=head[x];i;i=nxt[i]) if (dis[to[i]]>dis[x]+val[i]) { dis[to[i]]=dis[x]+val[i]; if (!vis[to[i]]) { vis[to[i]]= true ; q.push(to[i]); tim[to[i]]=tim[x]+1; if (tim[to[i]]>n) return false ; } } } return true ; } int main() { int opt,x,y,z; n=rd(),m=rd(); for ( int i=1;i<=m;i++) { opt=rd(); if (opt==1) {x=rd(),y=rd(),z=rd(),add(x,y,-z);} else if (opt==2) {x=rd(),y=rd(),z=rd(),add(y,x,z);} else {x=rd(),y=rd(),add(x,y,0),add(y,x,0);} } for ( int i=1;i<=n;i++) add(0,i,0); if (spfa()) puts ( "Yes" ); else puts ( "No" ); return 0; } |
小结:差分约束还是比较有意思的/xyx
| 欢迎来原网站坐坐! >原文链接<
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步