思路:虽然是最短路专题里的,但也很难想到是最短路,如果能通过这些关系想到图论可能会有些思路。我们把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\n",min(ans1,ans2)); } return 0; }