大致思路:
给你几个不等式,问你有没有解.....典型的差分方程判断有无解(负环)的题型。
那我先想好,求最长路吧,那就得把所有不等式化为>=的形式,先由题意列不等式再转化:
a比b至少多c元: a-b>=c ------------> a-b>=c ------->add(b,a,c)
a比b至多多cc元:a-b<=cc ---------> b-a>=-cc -------->add(a,b,-cc)
a和d存款一样多:a=d -------------> a-d>=0 , d-a >=0 ------>add2(d,a,0)
记得再插个超级源点!!!!!
然后就用spfa求最长路,如果同一个点加入队列的次数超过(n+1)次(因为多加了个超级源点!!!),则存在负环即无解。
我的代码:
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
#include<queue>
int n,m;
const int MAXN=1e4+5;
const int MAXM=1e7+5;
struct
{
int v,w;
int next;
}edge[MAXM];
int p[MAXN];
int dis[MAXN];
int cot[MAXN];
void init()
{
memset(p,-1,sizeof(p));
memset(dis,0x3f,sizeof(dis));
memset(cot,0,sizeof(cot));
}
int cnt=0;
void add(int u,int v,int w)
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=p[u];
p[u]=cnt;
cnt++;
}
void add2(int u,int v,int w)
{
add(u,v,w);
add(v,u,w);
}
queue<int> q;
bool isin[MAXN];
int flag=0;
void spfa(int s)
{
isin[s]=true;
dis[s]=0;
q.push(s);
while(q.empty()==false)
{
int u=q.front();
isin[q.front()]=false;
q.pop();
cot[s]++;
for(int i=p[u];i!=-1;i=edge[i].next)
{
if(dis[u]+edge[i].w>dis[edge[i].v])
{
dis[edge[i].v]=dis[u]+edge[i].w;
if(isin[edge[i].v]==false)
{
isin[edge[i].v]=true;
q.push(edge[i].v);
cot[edge[i].v]++;
if(cot[edge[i].v]>n+1)
{
flag=1;
return;
}
}
}
}
}
}
int main()
{
cin>>n>>m;
init();
while(m--)
{
int indicator;
cin>>indicator;
if(indicator==1)
{
int a,b,c;
cin>>a>>b>>c;
add(b,a,c);
}
else if(indicator==2)
{
int a,b,cc;
cin>>a>>b>>cc;
add(a,b,-cc);
}
else if(indicator==3)
{
int a,b;
add2(a,b,0);
}
}
for(int i=1;i<=n;i++)
add(0,i,0); //插入超级源点
spfa(0);
if(flag==0)
cout<<"Yes";
else
cout<<"No";
return 0;
}