50分求助
查看原帖
50分求助
80026
walk_alone楼主2021/1/20 21:37

蒟蒻刚刚搞清楚同余最短路是个咋回事就被这个题教训了……

#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
const int inf = 999999999;
struct node
{
    int id;
    int dis;
    bool operator <(const node &b)const
    {
        return dis > b.dis;
    }
};
int dis[3005], length[3005], tot;
bool vis[3005];
bool judge()//判断是否无解的一种情况:最小公约数大于等于2
{
    for (int i = 2; i <= tot; i++)
        if(length[i]%length[1]!=0)
            return 0;
    return 1;
}
void dijkstra(int s)//dijkstra的板子
{
    dis[s] = 0;
    priority_queue<node> q;
    q.push((node){s, 0});
    while(!q.empty())
    {
        node tp = q.top();
        q.pop();
        if(vis[tp.id])
            continue;
        vis[tp.id] = 1;
        for (int i = 2; i <= tot;i++)//不敢建边了,开到了五千万的边数组还是RE了
            if(dis[(tp.id+length[i])%length[1]]>dis[tp.id]+length[i])
            {
                dis[(tp.id + length[i]) % length[1]] = dis[tp.id] + length[i];
                q.push((node){(tp.id + length[i]) % length[1], dis[(tp.id + length[i]) % length[1]]});
            }
    }
    return;
}
int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n;i++)
    {
        int place = ++tot;//初始边所在位置
        scanf("%d", &length[tot]);
        for (int j = 1; j <= m && j < length[place]; j++)//切下来长度最长不能超过远长
            length[++tot] = length[place] - j;//切的木棍长度
    }
    sort(length + 1, length + tot + 1);
    if(length[1]==1 || judge())//当最小长度为1时所有长度均可表示,直接-1
    {
        printf("-1");
        return 0;
    }
    for (int i = 0; i < length[1]; i++)
        dis[i] = inf;
    dijkstra(0);
    int res = -1;
    for (int i = 1; i < length[1]; i++)//枚举最大长度
        res = max(res, dis[i]);
    printf("%d", res - length[1]);
    return 0;
}
2021/1/20 21:37
加载中...