排位赛的E题,纠结了好久,做的时候猜到就是用差分约束来做。
对于每个防御点作为一个点,
(1)由P条件可以知, a - b = c(随便假设个方向),化成不等式组得{a - b >= c && a - b <= c} ,在移向得{b - a <= -c && a - b <= c} (建边a ->b, len = -c & b->a, len=c)
(2)由V条件可知,a - b >= 1 即 b - a <= -1 (建边 a -> b, 长度为-1)
根据以上构图,注意,如果用SPFA做的话,必须加一个超级源点,令它到每个点距离<=0就好,然后该怎么做就怎么做,存在负环表示无解,否则存在正解。
如果不加源点的话可以用Bellman_ford()做,否则有些不在统一图上的点是搜不到的
转:
对于差分约束系统的一个资料参考:
1) 建图后求最短路(对应 <= 的差分约束)
从求最短路后分析开始。求最短路后一定有:d(u) + w(u,v) >= d(v) 转换为:d(v) – d(u) <= w(u,v)。然后这个式子与我们差分约束条件得到的不等式( X(a) - X(b) <= c )相似。
所以得到建图的规则为:一条b到a的边权值为c。
建图后求最短路即为一组解。
2) 建图后求最长路(对应 >= 的差分约束)
同上。求最长路后一定得到:d(u) + w(u,v) <= d(v) 转换为:d(v)-d(u)>=w(u,v)。然后对比差分约束条件的不等式( X(a) - X(b) >= c )。
所以得到建图的规则为:一条b到a的边权值为c。
建图后求最长路即为一组解。
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int INF=999999;
struct node
{
int v;
int len;
};
int n,m;
vector<node>map[1002];
int spfa()
{
int vis[1009];
memset(vis,0,sizeof(vis));
int inq[1001];
memset(inq,0,sizeof(inq));
int dist[10001];
queue<int>Q;
for(int i=0;i<=n;i++)
dist[i]=INF;
while (!Q.empty())
dist[0]=INF;
Q.push(0);
vis[0]=1;
Q.push(0);
while(!Q.empty())
{
int top=Q.front();
Q.pop();
inq[top]=0;
for(int i=0;i<map[top].size();i++)
{
if(dist[map[top][i].v]>dist[top]+map[top][i].len)
{
dist[map[top][i].v]=dist[top]+map[top][i].len;
if(!inq[map[top][i].v])
{
Q.push(map[top][i].v);
inq[map[top][i].v]=1;
}
if(++vis[map[top][i].v]>=n)
return 0;
}
}
}
return 1;
}
int main()
{
while(cin>>n>>m)
{
for(int i=0;i<=n;i++)
map[i].clear();
char f;
int u,v,c;
for(int i=0;i<m;i++)
{
cin>>f;
if(f=='P')
{
cin>>u>>v>>c;
node tmp;
tmp.len=c;
tmp.v=u;
map[v].push_back(tmp);
tmp.len=-c;
tmp.v=v;
map[u].push_back(tmp);
}
else
{
cin>>u>>v;
node t;
t.len=-1;
t.v=v;
map[u].push_back(t);
}
}
for (int i=0; i<=n; i++)
{
node k;
k.v=i;
k.len=0;
map[0].push_back(k);
}
if(spfa())
cout<<"Unreliable"<<endl;
else
cout<<"Reliable"<<endl;
}
return 0;
}
#include <string>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int INF=999999;
struct node
{
int v;
int len;
};
int n,m;
vector<node>map[1002];
int spfa()
{
int vis[1009];
memset(vis,0,sizeof(vis));
int inq[1001];
memset(inq,0,sizeof(inq));
int dist[10001];
queue<int>Q;
for(int i=0;i<=n;i++)
dist[i]=INF;
while (!Q.empty())
dist[0]=INF;
Q.push(0);
vis[0]=1;
Q.push(0);
while(!Q.empty())
{
int top=Q.front();
Q.pop();
inq[top]=0;
for(int i=0;i<map[top].size();i++)
{
if(dist[map[top][i].v]>dist[top]+map[top][i].len)
{
dist[map[top][i].v]=dist[top]+map[top][i].len;
if(!inq[map[top][i].v])
{
Q.push(map[top][i].v);
inq[map[top][i].v]=1;
}
if(++vis[map[top][i].v]>=n)
return 0;
}
}
}
return 1;
}
int main()
{
while(cin>>n>>m)
{
for(int i=0;i<=n;i++)
map[i].clear();
char f;
int u,v,c;
for(int i=0;i<m;i++)
{
cin>>f;
if(f=='P')
{
cin>>u>>v>>c;
node tmp;
tmp.len=c;
tmp.v=u;
map[v].push_back(tmp);
tmp.len=-c;
tmp.v=v;
map[u].push_back(tmp);
}
else
{
cin>>u>>v;
node t;
t.len=-1;
t.v=v;
map[u].push_back(t);
}
}
for (int i=0; i<=n; i++)
{
node k;
k.v=i;
k.len=0;
map[0].push_back(k);
}
if(spfa())
cout<<"Unreliable"<<endl;
else
cout<<"Reliable"<<endl;
}
return 0;
}