Problem Description(hdu-4370)

解题思路

读懂题很考人。很容易就当成水题来做了。 借鉴网上的思路。转化成最短路来做。

由(1)得知,1结点只有一个出度 由(2)得知,n结点只有一个入度 由(3)得知,其余结点出度 == 入度

一下两种情况满足上述三种规则: A) 1到n形成一条路—>求1到n的最短路 B) 1和n没有路—> 1和n各自形成非自环的闭环。 求两者的最小值,即为题目要求的∑(Cij * Xij) 细节:求非自环的闭环:不将dist[start]初始化为0,将其初始化为inf(也就是说到start到start的路不再是自环,需要另找一条路),在队列q中放入与之相邻的点。dist[start] 则是满足要求的最小环。

代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <stack>
#define ll long long
//#define local

using namespace std;

const int MOD = 1e9+7;
const int inf = 0x3f3f3f3f;
const int maxn = 305;
int N;
int c[maxn][maxn];
int inque[maxn];
int dist[maxn];

void spfa (int start, int end) {
    queue<int> q;
    inque[start] = 0;
    dist[start] = inf;
    for (int i = 1; i <= N; ++i) {
        if(i == start) continue;
        dist[i] = c[start][i];
        inque[i] = 1;
        q.push(i);
    }
    while (q.size()) {
        int u = q.front();
        q.pop();
        inque[u] = 0;
        for (int i = 1; i <= N; i++) {
            if(dist[i] > dist[u]+c[u][i]) {
                dist[i] = dist[u]+c[u][i];
                if(!inque[i]) {
                    inque[i] = 1;
                    q.push(i);
                }
            }
        }
    }
}

int main() {
#ifdef local
    if(freopen("/Users/Andrew/Desktop/data.txt", "r", stdin) == NULL) printf("can't open this file!\n");
#endif
    while (cin >> N) {
        for (int i = 1; i <= N; ++i)
            for (int j = 1; j <= N; ++j)
                scanf("%d", &c[i][j]);
        spfa(1, N);
        int ans = dist[N];
        int c1 = dist[1];
        spfa(N, N);
        int c2 = dist[N];
        printf("%d\n", min(ans, c1+c2));
    }
#ifdef local
    fclose(stdin);
#endif
    return 0;
}