HDU 4370 0 or 1(转化为最短路)题解

思路:虽然是最短路专题里的,但也很难想到是最短路,如果能通过这些关系想到图论可能会有些思路。我们把X数组看做邻接矩阵,那么三个条件就转化为了:1、1的出度为1;2、n的入度为1;3、2~n-1的出度等于入度。C*X则是路径花费,最后求满足这些条件的路径的最少花费。满足这些条件的情况有两种:一是1到n的一条最短路径,二是1成自环,n成自环。最后找出两者最小值。

这里要注意下spfa的写法,因为需要成自环,所以dist[st]初始化为INF,保证成自环而非0;先让其他点入队。

代码:

#include<cstdio>
#include<set>
#include<cmath>
#include<stack>
#include<vector>
#include<queue>
#include<cstring>
#include<string>
#include<sstream>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 300+5;
const int INF = 0x3f3f3f3f;
int cost[maxn][maxn];
bool vis[maxn];
int cnt[maxn];
int dist[maxn];
bool spfa(int st,int n){
    memset(vis,false,sizeof(vis));
    vis[st] = true;
    queue<int> q;
    while(!q.empty()) q.pop();
    for(int i = 1;i <= n;i++){
        if(i != st) q.push(i);
        dist[i] = cost[st][i];
    }
    dist[st] = INF;
    memset(cnt,0,sizeof(cnt));
    cnt[st] = 1;
    while(!q.empty()){
        int u = q.front();
        q.pop();
        vis[u] = false;
        for(int v = 1;v <= n;v++){
            if(dist[v] > dist[u] + cost[u][v]){
                dist[v] = dist[u] + cost[u][v];
                if(!vis[v]){
                    vis[v] = true;
                    q.push(v);
                    if(++cnt[v] > n) return false;
                }
            }
        }
    }
    return true;
}
int main(){
    int n;
    while(~scanf("%d",&n)){
        for(int i = 1;i <= n;i++){
            for(int j = 1;j <= n;j++){
                int w;
                scanf("%d",&w);
                cost[i][j] = w;
            }
        }
        spfa(1,n);
        int ans1 = dist[n];
        int ans2 = dist[1];
        spfa(n,n);
        ans2 += dist[n];
        printf("%d
",min(ans1,ans2));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/KirinSB/p/9475137.html