差分约束系统详解请戳: 差分约束详解
求最小值:(差分不等式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();//int
while(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>=-a
cur.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;
}
将>和<变成>=和<=.因为差分约束只限于>=和<=
同时加了一个超级源点保安图的连通性
这道题就两个很明显的公式。不用推也可以了。
#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";
else
cout<<"lamentable kingdom\n";
}
}
其中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();//int
while(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)>=0
cur.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();//int
while(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");
else
printf("%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;
}