玄关 为什么最长路可行 最短路不行wa很多
查看原帖
玄关 为什么最长路可行 最短路不行wa很多
756825
Ze_king楼主2025/8/29 18:49

rt

// 最短路
// 我的思路是通过变形成v<=u+w的形式w∈(0,-1)这样先满足小朋友的相对关系
// 然后添加超级零点保证联通性 s->u (0) 这条边实际上也是一个约束 相当于u<=s(0)+0(s是0是因为s只有出边所以s会保持原始值) 会导致所有节点 u<=0
// 这时候通过差分的平移不变性 给每个节点加上一个值 来保证u>=1
// 但是卡spfa。。。
// magic 用来防止spfa超时 神秘小优化

# include <bits/stdc++.h>
using namespace std;
# define INF LLONG_MAX

vector<pair<int,int>> e[100005];
long long n,m,ans;
long long dist[100005];
bool inq[100005];
int cnt[100005];
int magic;
void spfa(){
    fill(dist,dist + 100005,INF); 
    dist[0]=0;
    queue <int> q;
    q.push(0);
    inq[0]=true; 
    while (!q.empty()){
        int u = q.front();
        q.pop(); inq[u] = false;
        //if (++magic > 1e7) {cout << -1; return;}
        for (auto edge : e[u]){
            int v = edge.first;
            int w = edge.second;
            if (dist[v] > dist[u] + w){
                dist[v] = dist[u] + w;
                cnt[v] = cnt[u] + 1;
                if (cnt[v] > n){
                    cout << -1;
                    return;
                }
                if (!inq[v]){
                    q.push(v);
                    inq[v]=true;
                }
            }
        }
    }
    long long themin = INF;
    for(int i = 1; i <= n; i++){
        themin = min(themin,dist[i]);
    }
    for (int i = 1; i <= n; i++){
        ans += dist[i] + (1 - themin);       //保证最小值大于1;
    }
    cout << ans;
}

int main() { 
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    
    cin >> n >> m;
    for (int i = 1; i <= m; i++){
        int x,a,b;
        cin >> x >> a >> b;
        switch (x){
            case 1:
                e[b].push_back({a,0});
                e[a].push_back({b,0});
                break;
            case 2:
                e[b].push_back({a,-1});
                break;
            case 3:
                e[a].push_back({b,0});
                break;
            case 4:
                e[a].push_back({b,-1});
                break;
            case 5:
                e[b].push_back({a,0});
                break;
        }
    }
    for (int i = 1; i <= n; i++){
        e[0].push_back({i,-INF});
    }
    spfa();
    return 0;
}

// // 最长路
// // 可以变形成v>=u+w∈(0,1) 发现这是最长路的形式
// // 而spfa只要把松弛条件反过来变成 v < u+w 就是最长路 (正确性易证)
// // 而且对于 u >= 1 的条件,可以直接从超级零点引一条1的出边 相当于 u >= s(0) + 1
// // 刚好可以避免平移的操作
// // magic 用来防止spfa超时 神秘小优化

// # include <bits/stdc++.h>
// using namespace std;
// # define INF LLONG_MAX

// vector<pair<int,int>> e[100005];
// long long n,m,ans;
// long long dist[100005];
// bool inq[100005];
// int cnt[100005];
// int magic;
// void spfa(){
//     fill(dist,dist + 100005,-INF);
//     dist[0]=0;
//     queue <int> q;
//     q.push(0);
//     inq[0]=true; 
//     while (!q.empty()){
//         int u = q.front();
//         q.pop(); inq[u] = false;
//         if (++magic > 1e7) {cout << -1; return;}
//         for (auto edge : e[u]){
//             int v = edge.first;
//             int w = edge.second;
//             if (dist[v] < dist[u] + w){
//                 dist[v] = dist[u] + w;
//                 cnt[v] = cnt[u] + 1;
//                 if (cnt[v] > n){
//                     cout << -1;
//                     return;
//                 }
//                 if (!inq[v]){
//                     q.push(v);
//                     inq[v]=true;
//                 }
//             }
//         }
//     }
//     for (int i = 1; i <= n; i++){
//         ans += dist[i];       //保证最小值大于1;
//     }
//     cout << ans;
// }

// int main() { 
//     ios::sync_with_stdio(false);
//     cin.tie(nullptr);
//     cin >> n >> m;
//     for (int i = 1; i <= m; i++){
//         int x,a,b;
//         cin >> x >> a >> b;
//         switch (x){
//             case 1:
//                 e[b].push_back({a,0});
//                 e[a].push_back({b,0});
//                 break;
//             case 2:
//                 e[a].push_back({b,1});
//                 break;
//             case 3:
//                 e[b].push_back({a,0});
//                 break;
//             case 4:
//                 e[b].push_back({a,1});
//                 break;
//             case 5:
//                 e[a].push_back({b,0});
//                 break;
//         }
//     }
//     for (int i = 1; i <= n; i++){
//         e[0].push_back({i,1});
//     }
//     spfa();
//     return 0;
// }
2025/8/29 18:49
加载中...