差分约束题集:zoj 2770&poj1364&poj1275&poj3169
来源:互联网 发布:网络语言暴力可怕 编辑:程序博客网 时间:2024/04/29 03:16
差分约束系统详解请戳: 差分约束详解
zoj2770
求最小值:(差分不等式a-b>=c,求最长路,得到最小值)
由于
①:Ai>=0 >>>> Si-S(i-1)>=0
②:Ai<=a >>>> S(i-1)-Si>=-a
③:Si-S0>=0(0可以视为新增上的一个源点)
④:Sb-S(a-1)>=c
根据上公式就可以建立图了
#include <map>#include <set>#include <queue>#include <stack>#include <math.h>#include <vector>#include <cstdio>#include <string>#include<string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;int dist[1010];int n,m,a,b,c;struct edge{int to,cost;}cur;vector<edge>vec[1010];inline void read(int &m)//int{int x=0,f=1;char ch=getchar();//intwhile(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}m=x*f;}bool spfa() //(差分不等式a-b>=c,求最长路,得到最小值){int cnt[1010];bool vis[1010];for(int i=1;i<=n;i++)dist[i]=-1111111111;memset(cnt,0,sizeof(cnt));memset(vis,0,sizeof(vis));vis[0]=1;dist[0]=0;queue<int>que;que.push(0);while(!que.empty()){int v=que.front();que.pop();if(++cnt[v]>=n)return 0;vis[v]=0;for(int i=0;i<vec[v].size();i++){edge temp=vec[v][i];if(dist[temp.to]<dist[v]+temp.cost) //其实源点松弛后所有点的dist[]全部变为0了且全部入队。和另一个方法差不多{dist[temp.to]=dist[v]+temp.cost;if(!vis[temp.to]){vis[temp.to]=1;que.push(temp.to);}}}}return 1;}int main(){while(~scanf("%d %d",&n,&m)){for(int i=0;i<=n;i++)vec[i].clear();for(int i=1;i<=n;i++){read(a);cur.to=i;cur.cost=0;vec[i-1].push_back(cur); //Ai>=0 Si-S(i-1)>=0 cur.to=i-1;cur.cost=-a;vec[i].push_back(cur); //Ai<=a S(i-1)-Si>=-acur.to=i;cur.cost=0;vec[0].push_back(cur); //Si-S0>=0 //0点为新添上去的源点,与其他节点建立关系}for(int i=1;i<=m;i++){read(a),read(b),read(c);cur.to=b;cur.cost=c;vec[a-1].push_back(cur); //Sb-Sa-1>=c}if(spfa())printf("%d\n",dist[n]);else printf("Bad Estimations\n");}return 0;}
poj1364.
将>和<变成>=和<=.因为差分约束只限于>=和<=
同时加了一个超级源点保安图的连通性
这道题就两个很明显的公式。不用推也可以了。
#include <map>#include <set>#include <queue>#include <stack>#include <math.h>#include <vector>#include <cstdio>#include <string>#include<string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;int n,m;struct edge{int to,cost;}cur;vector<edge>vec[110];bool spfa(){bool vis[110];int dist[110],cnt[110];memset(vis,0,sizeof(vis));memset(cnt,0,sizeof(cnt));fill(dist,dist+110,10000000);vis[n+1]=1;dist[n+1]=0;queue<int>que;que.push(n+1);while(!que.empty()){int v=que.front();que.pop();vis[v]=0;if(++cnt[v]>n)return 1; //不包括超级源点的话,实际上起作用的就n+1个节点for(int i=0;i<vec[v].size();i++){edge temp=vec[v][i];if(dist[temp.to]>dist[v]+temp.cost){dist[temp.to]=dist[v]+temp.cost;if(!vis[temp.to])vis[temp.to]=1,que.push(temp.to);}}}return 0;}int main(){while(cin>>n&&n){cin>>m;for(int i=0;i<=n+1;i++)vec[i].clear();while(m--){int a,b,c;string st;cin>>a>>b>>st>>c;b+=a;if(st[0]=='l') //全部转换成<=.....{cur.to=b;cur.cost=c-1;vec[a-1].push_back(cur);}else{cur.to=a-1;cur.cost=-c-1;vec[b].push_back(cur);}}for(int i=0;i<=n;i++) //新加入的超级源点,与其他点相邻,距离为0{cur.to=i;cur.cost=0;vec[n+1].push_back(cur);}if(spfa())cout<<"successful conspiracy\n";elsecout<<"lamentable kingdom\n";}}
poj1275
其中Si-Sj这条公式是根据
①s[ I ]-s[ I-8 ]>=r[ I ], 8<=I<=23
②s[ 23 ]+s[ I ]-s[ I+16 ]>=r[ I ], 0<=I<=7
整理而得
图片中的第三个公式S[23] - S[-1] >= sum;是必须的。
至于为什么请戳:为嘛是必须哒?
代码:
#include <map>#include <set>#include <queue>#include <stack>#include <math.h>#include <vector>#include <cstdio>#include <string>#include<string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;int cas,n,k;int r[30],num[30];bool flag;struct edge{int to,cost;}cur;vector<edge>vec[30];inline void read(int &m)//int{int x=0,f=1;char ch=getchar();//intwhile(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}m=x*f;}void BuildGraph(int sum){for(int i=0;i<=25;i++)vec[i].clear();cur.to=24;cur.cost=sum;vec[0].push_back(cur);for(int i=1;i<=24;i++){cur.to=i;cur.cost=0;vec[i-1].push_back(cur); //Si-S(i-1)>=0cur.to=i-1;cur.cost=-num[i];vec[i].push_back(cur); //S(i-1)-Si>=-t[i]}for(int i=1;i<=8;i++){cur.to=i;cur.cost=r[i]-sum;vec[i+16].push_back(cur);}for(int i=9;i<=24;i++){cur.to=i;cur.cost=r[i];vec[i-8].push_back(cur);}}bool spfa(int sum){int cnt[30],dist[30];bool vis[30];for(int i=0;i<=25;i++){cnt[i]=0;vis[i]=0;dist[i]=-11111111;}vis[0]=1;dist[0]=0;queue<int>que;que.push(0);while(!que.empty()){int v=que.front();que.pop();vis[v]=0;if(++cnt[v]>=25)return 0;for(int i=0;i<vec[v].size();i++){edge temp=vec[v][i];if(dist[temp.to]<dist[v]+temp.cost){dist[temp.to]=dist[v]+temp.cost;if(!vis[temp.to])vis[temp.to]=1,que.push(temp.to);}}}if(dist[24]==sum)return 1;return 0;}int main(){read(cas);while(cas--){memset(num,0,sizeof(num));for(int i=1;i<=24;i++)read(r[i]);read(n);for(int i=1;i<=n;i++){read(k);num[k+1]++;}flag=0;for(int i=0;i<=n;i++){BuildGraph(i);if(spfa(i)){flag=1;printf("%d\n",i);break;}}if(!flag)printf("No Solution\n"); }return 0;}
poj3169
特别简单的一道题。
应该有三条公式的:
①ML:b-a<=c
②MD:b-a>=c
③题意:Si-S(i-1)>=0(可是加上这句话就错。不知道为啥).
#include <map>#include <set>#include <queue>#include <stack>#include <math.h>#include <vector>#include <cstdio>#include <string>#include<string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;int n,ml,md;const int maxn=10000000;struct edge{int to,cost;}cur;vector<edge>vec[1010];inline void read(int &m)//int{int x=0,f=1;char ch=getchar();//intwhile(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}m=x*f;}void spfa(){bool vis[1010];int cnt[1010],dist[1010];memset(vis,0,sizeof(vis));memset(cnt,0,sizeof(cnt));fill(dist,dist+1010,maxn);dist[1]=0;queue<int>que;que.push(1);while(!que.empty()){int v=que.front();que.pop();vis[v]=0;if(++cnt[v]>=n){printf("-1\n");return;}for(int i=0;i<vec[v].size();i++){edge temp=vec[v][i];if(dist[temp.to]>dist[v]+temp.cost){dist[temp.to]=dist[v]+temp.cost;if(!vis[temp.to])vis[temp.to]=1,que.push(temp.to);}}}if(dist[n]==maxn)printf("-2\n");elseprintf("%d\n",dist[n]);}int main(){read(n),read(ml),read(md);int a,b,c;while(ml--){read(a),read(b),read(c);cur.to=b;cur.cost=c;vec[a].push_back(cur);}while(md--){read(a),read(b),read(c);cur.to=a;cur.cost=-c;vec[b].push_back(cur);}/*for(int i=1;i<=n;i++){cur.to=i-1;cur.cost=0;vec[i].push_back(cur);}*/spfa();return 0;}
0 0
- 差分约束题集:zoj 2770&poj1364&poj1275&poj3169
- 差分约束小结(poj1201,poj1716,poj1364,poj3159,poj3169,poj1275)
- Poj1275 差分约束
- poj1275 差分约束
- poj1275差分约束
- poj1364 差分约束
- 差分约束 poj1364
- POJ3169 差分约束
- poj3169(差分约束)
- poj3169(差分约束)
- poj3169 差分约束
- POJ3169差分约束
- POJ3169差分约束
- poj1275(差分约束系统)
- poj1275(差分约束)
- hdu1384&&poj1364差分约束
- POJ1364 差分约束系统
- poj1364 King --- 差分约束
- hdu-2048-神、上帝以及老天爷(错序排列)
- 数据挖掘笔记-特征选择-整体汇总
- Ambiguous method call. Both getClass () in Object and getClass () in Object match.
- SSH三大框架初探之Spring
- 无聊的周五,明天放假。
- 差分约束题集:zoj 2770&poj1364&poj1275&poj3169
- UITextView使用方法
- nyoj214单调递增子序列(二)
- android权限列表
- 进程上下文与中断上下文
- Single-Pass and Two-Model Retraining
- 1408081640-hd-畅通工程.cpp
- memcpy函数的用法
- java语言学习003_开发环境基础配置和安装(jdk,jre,eclipse&myeclipse)