题目大意:
国王有一个傻儿子,只会判断在给出的序列S={a1,a2,a3,a4...ai...at}中,ai+a(i+1)+a(i+2)+...+a(i+n)<ki或ai+a(i+1)+a(i+2)+...+a(i+n)>ki,其中测试数据中给出的gt是'>',lt是'<'.有时候这个傻儿子连这也会判断错,当他错了时他不能说自己错(因为是国王的儿子嘛),所以他需要构造一个为序列S1来替代序列S 。问有没有这样一个序列。
思路:
这题区别之前做的几道题, 之前许多都是问的是从1-n有没有解, 1-n的最大距离是多少,最高最低的最远距离多少,这些都是直接明确出了哪几个点,而这题问你这个有没有解,我们知道无解是负环(针对最短路), 也就是找,图中有没有负环, 只要有一个,说明他就是错的, 因此这题要把所有的联通块都找一遍(之前可能是不联通的, 前面一些题不联通可能代表任意解,无穷大什么的),看有没有负环~
a-b<k,a-b>k的形式,需要变换成a-b<=k-1,a-b>=k+1的形式。由于本题要找负边权环,那么肯定要找最短路,所以将a-b>=k+1的形式都转换为b-a<=-k-1。
两个约束条件:
a-b<=k-1
b-a<=-k-1
找负边权环的方法很简单:如果某个节点入队超过总的节点个数,那么说明有负边权环。
这里我用spfa, 解决不联通有两种方法, 一个是建立一个超级源点,跟每个点连起来,权值为0,从超级源点出发,另一个方法是先把所有的点都扔到队列里,所有dis赋值0代表刚开始都是连通的。
超级源点代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int INF = 2e9;
const int maxn = 105;
int n, m, x, y, d;
struct node
{
int to, w;
node(){}
node(int tt, int ww) : to(tt), w(ww){}
};
vector<node> v[maxn];
int book[maxn], cnt[maxn], dis[maxn];
char cmd[50];
void spfa()
{
memset(book, 0, sizeof(book));
for(int i = 0; i < maxn; i++) dis[i] = INF;
dis[n+1] = 0;
book[n+1] = 1;
cnt[n+1] = 1;
queue<int> q;
q.push(n+1);
while(!q.empty())
{
int u = q.front();
q.pop();
book[u] = 0;
for(int i = 0; i < v[u].size(); i++)
{
int to = v[u][i].to;
if(dis[u]+v[u][i].w < dis[to])
{
dis[to] = dis[u] + v[u][i].w;
if(!book[to])
{
if(++cnt[to] > n+1)
{
puts("successful conspiracy");
return ;
}
book[to] = 1;
q.push(to);
}
}
}
}
puts("lamentable kingdom");
return ;
}
int main()
{
while(~scanf("%d%d", &n, &m), n)
{
memset(book, 0, sizeof(book));
memset(cnt, 0, sizeof(cnt));
for(int i = 0; i < maxn; i++)
v[i].clear();
for(int i = 1; i <= m; i++)
{
scanf("%d%d %s%d", &x, &y, cmd, &d);
if(cmd[0] == 'g')
v[x+y].push_back(node(x-1, -d-1));
else
v[x-1].push_back((node(x+y, d-1)));
}
for(int i = 0; i <= n; i++)
v[n+1].push_back(node(i, 0));
spfa();
}
return 0;
}
都扔进队列代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int INF = 2e9;
const int maxn = 105;
int n, m, x, y, d;
struct node
{
int to, w;
node(){}
node(int tt, int ww) : to(tt), w(ww){}
};
vector<node> v[maxn];
int book[maxn], cnt[maxn], dis[maxn];
char cmd[50];
void spfa()
{
memset(book, 0, sizeof(book));
queue<int> q;
for(int i = 0; i <= n; i++)
{
q.push(i);
book[i] = 1;
cnt[i] = 1;
dis[i] = 0;
}
while(!q.empty())
{
int u = q.front();
q.pop();
book[u] = 0;
for(int i = 0; i < v[u].size(); i++)
{
int to = v[u][i].to;
if(dis[u]+v[u][i].w < dis[to])
{
dis[to] = dis[u] + v[u][i].w;
if(!book[to])
{
if(++cnt[to] > n+1)
{
puts("successful conspiracy");
return ;
}
book[to] = 1;
q.push(to);
}
}
}
}
puts("lamentable kingdom");
return ;
}
int main()
{
while(~scanf("%d%d", &n, &m), n)
{
memset(book, 0, sizeof(book));
memset(cnt, 0, sizeof(cnt));
for(int i = 0; i < maxn; i++)
v[i].clear();
for(int i = 1; i <= m; i++)
{
scanf("%d%d %s%d", &x, &y, cmd, &d);
if(cmd[0] == 'g')
v[x+y].push_back(node(x-1, -d-1));
else
v[x-1].push_back((node(x+y, d-1)));
}
spfa();
}
return 0;
}