P1993 小K的農場
阿新 • • 發佈:2018-07-01
最長路 -c turn tps scan 差分 常數 mat 系列 的邊,那麽我們我們就可以跑最短路。(或連著一條權值為\(c\)的邊,跑最長路)
P1993 小K的農場
這個題,涉及到的知識點是差分約束。
差分約束,是用來判斷不等式是否有解集和求出一組特解的一種方法。
具體是使用最短(長)路算法。
觀察最短路算法,有一個類似與三角形三邊關系的不等式。
\[dis[a]+weight>=dis[b]\]
其中a與b之間直接連了一條邊權為weight的邊。 通過我們熟練地水做一系列最短路,我們一眼就能看出這是正確的。
那我們再來看一個不等式\(x_1-x_2<=c\),其中\(c\)為常數
變一個型
\[x_1<=x_2+c\]
\[x_2+c>=x_1\]
如果我們把\(x_1,x_2\)看做一個點。中間連著一條權值為\(-c\)
我們先把權值都取負,這樣就可以跑最短路。
為什麽? 首先我們是用絕對值來保存特解的。然後跑最短路就是要讓絕對值最大(要滿足所有的不等式)
然後對於判斷有無解,就是判斷有無負環
比如說\(a>=b+1,b>=c+1,c>=a+1\)這肯定無解。具體的說明,自己YY去吧
判斷負環還是使用玄學時間復雜度的DFS啦
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int maxn=10100; struct node { int point; int nxt; int weight; }; int head[maxn],tail; node line[maxn<<1]; void add(int a,int b,int c) { line[++tail].point=b; line[tail].weight=c; line[tail].nxt=head[a]; head[a]=tail; } bool flag=false; int dis[maxn]; bool vis[maxn]; void dfs(int now) { if(flag) return ; if(vis[now]) { flag=true; return ; } vis[now]=true; for(int i=head[now];i;i=line[i].nxt) { if(dis[line[i].point]>dis[now]+line[i].weight) { dis[line[i].point]=dis[now]+line[i].weight; dfs(line[i].point); if(flag) return ; } } vis[now]=false; } int main() { int n,m; scanf("%d%d",&n,&m); int a,b,c,d; for(int i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); if(a==1||a==2) scanf("%d",&d); if(a==1) add(c,b,-d);//b-c>=d b>=c+d; if(a==2) add(b,c,d);//b-c<=d c-b>=-d c>=b-d; if(a==3) add(b,c,0),add(c,b,0); } for(int i=1;i<=n;i++) { dfs(i); if(flag) { printf("No"); return 0; } } printf("Yes"); return 0; } /* 3 3 3 1 2 1 1 3 1 2 2 3 2 */
P1993 小K的農場