【题目大意】
n头牛从小到大排,它们之间某些距离不能大于一个值,某些距离不能小于一个值,求第一头牛和第N头牛之间距离的最大值。
【思路】
由题意可以得到以下不等式d[AL]+DL≥d[BL];d[BD]+(-DD)≥d[AD];d[i+1]+0≥d[i],显然是差分约束系统。即构造从AL到BL权值为DL的边,从BD到AD构造权值为-DD的负边,从i+1到i构造权值为0的边。最后求最短路径。安利一个证明(点我)。
对于差分约束系统要注意的是,如果要求最大距离,用最短路径;求最小距离,用最长路径,要根据实际情况判断。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 const int MAXN=100000+5; 6 struct Rec 7 { 8 int ori,des,len; 9 bool operator < (const Rec &x) const 10 { 11 return len>x.len; 12 } 13 }edge[MAXN*5]; 14 int par[MAXN*2],height[MAXN*2]; 15 int n,m,r; 16 /*n代表女兵,m代表男兵,这里不需要用到二分图;r代表关系数*/ 17 int ans; 18 19 void initset() 20 { 21 for (int i=0;i<(n+m);i++) 22 { 23 par[i]=i; 24 height[i]=0; 25 } 26 } 27 28 int find(int x) 29 { 30 int r=x,temp; 31 while (par[r]!=r) r=par[r]; 32 while (x!=r) 33 { 34 temp=par[x]; 35 par[x]=r; 36 x=temp; 37 } 38 return (r); 39 } 40 41 void unionset(int fa,int fb) 42 { 43 if (height[fa]>=height[fb]) 44 { 45 par[fb]=fa; 46 if (height[fa]==height[fb]) height[fa]++; 47 } 48 else 49 par[fa]=fb; 50 } 51 52 int main() 53 { 54 int kase; 55 scanf("%d",&kase); 56 for (int cases=0;cases<kase;cases++) 57 { 58 scanf("%d%d%d",&n,&m,&r); 59 int ans=10000*(m+n); 60 for (int i=0;i<r;i++) 61 { 62 int u,v,w; 63 scanf("%d%d%d",&u,&v,&w); 64 edge[i].ori=u; 65 edge[i].des=v+n; 66 edge[i].len=w; 67 } 68 sort(edge,edge+r); 69 initset(); 70 for (int i=0;i<r;i++) 71 { 72 int fa=find(edge[i].ori); 73 int fb=find(edge[i].des); 74 if (fa!=fb) 75 { 76 unionset(fa,fb); 77 ans-=edge[i].len; 78 } 79 } 80 cout<<ans<<endl; 81 } 82 system("pause"); 83 return 0; 84 }
时间: 2024-10-12 04:55:44