差分约束题集: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
原创粉丝点击