1001. http://acm.hdu.edu.cn/showproblem.php?pid=4370
神一样的题目,用图论的思想建模,建立1~n一共n各点。
X12+X13+...X1n=1
2.X1n+X2n+...Xn-1n=1
理解为点1的出度为1,n点的入度为1;
将矩阵理解为边上的权值,那么可以理解为:
1. 从1到n的最短路
2.1和n各自的自环。
标程写了一个优先队列优化的dijikstra,orz一下,虽然忘记考虑自环了。
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
#define MAXN 330
#define INF 100000000
int n;
int dis[MAXN];
int g[MAXN][MAXN];
bool vis[MAXN];
priority_queue < pair<int,int> > pq;
int dijkstra()
{
int i,S=0,T=n-1;
vis[0]=dis[0]=0;
pq.push(make_pair(0,S));
for(i=1;i<n;i++) dis[i]=INF,vis[i]=false;
while(!pq.empty())
{
int u=pq.top().second;
pq.pop();
if(vis[u]) continue;
vis[u]=true;
for(i=0;i<n;i++)
{
if(dis[i]>dis[u]+g[u][i])
{
dis[i]=dis[u]+g[u][i];
pq.push(make_pair(-dis[i],i));
}
}
}
return dis[T];
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
while(~scanf("%d",&n))
{
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++) scanf("%d",&g[i][j]);
printf("%d\n",dijkstra());
}
return 0;
}
自己写的dijisktra:明显挫很多啊
#include <cstdio>
#include <iostream>
using namespace std;
//复杂度是:O(N^2)
const int maxn = 330;
const int INF = (1 << 30);
int mat[maxn][maxn];
//s代表起点,d代表终点,N代表矩阵大小,不能处理负数
int dijkstra(int s, int d, int n) {
bool vis[maxn];
int dis[maxn], k = INF, one = -1;
memset(vis, false, sizeof(vis));
fill(dis, dis + n, INF);
vis[s] = true;
dis[s] = 0;
for(int i = 0; i < n; i++) dis[i] = mat[s][i];
while(one != d) {
k = INF;
for(int i = 0; i < n; i++) if(dis[i] < k && !vis[i]) { one = i, k = dis[i]; }
vis[one] = true;
//cout << "here" << one << endl;
for(int i = 0; i < n; i++) if(dis[i] > dis[one] + mat[one][i]) dis[i] = dis[one] + mat[one][i];
}
return dis[d];
}
int main() {
int n;
while(~scanf("%d", &n)) {
for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) scanf("%d", &mat[i][j]);
for(int i = 0; i < n; i++) mat[i][i] = 0;
printf("%d\n", dijkstra(0, n - 1, n));
}
return 0;
}