您的位置:首页 > 其它

USACO Sweet Butter 解题报告

2013-04-03 21:54 344 查看
刚开始用Floyd Warshall算法求每对节点的最短路径,时间复杂度为v^3,空间上用的是邻接矩阵,结果超时。总结:这种方法适合于密集图。

后来考虑用dijsktra算法求单源最短路径,但是heap实现起来比较复杂,还得多个时间复杂度为O(logn)的decreasemin方法。网上看解题报告,看到了Shortest_Path_Faster_Algorithm。于是去wikipedia(http://en.wikipedia.org/wiki/Shortest_Path_Faster_Algorithm)上查看。思路很简单,据称最坏时间复杂
度非常坏,但在稀疏图中的时间复杂度好,为O(E),并且可以应用在(无负环)的负数权值图中。于是照着伪代码实现了。效果非常好。之后照着wikipedia后面介绍的优化方法写了下,也很简单,也有时间上的提升。

TASK: butter
LANG: C++

Compiling...
Compile: OK

Executing...
Test 1: TEST OK [0.000 secs, 5868 KB]
Test 2: TEST OK [0.000 secs, 5868 KB]
Test 3: TEST OK [0.000 secs, 5868 KB]
Test 4: TEST OK [0.000 secs, 5868 KB]
Test 5: TEST OK [0.000 secs, 5868 KB]
Test 6: TEST OK [0.000 secs, 5868 KB]
Test 7: TEST OK [0.011 secs, 5868 KB]
Test 8: TEST OK [0.022 secs, 5868 KB]
Test 9: TEST OK [0.043 secs, 5868 KB]
Test 10: TEST OK [0.043 secs, 5868 KB]

All tests OK.

附注:一块草地上可以有不止一头牛。

代码如下:

/*
ID: thestor1
LANG: C++
TASK: butter
*/
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cassert>
#include <string>
#include <algorithm>
#include <stack>
#include <set>
#include <queue>

using namespace std;

const int P = 800;
const int infinity = 180000;

int dis[P][P];

struct Edge{
int v;
int w;
Edge *next;
Edge(int v, int w)
{
this->v = v;
this->w = w;
this->next = NULL;
}
};

struct Vertex{
int u;
Edge *adj;
Vertex(int i)
{
this->u = i;
adj = NULL;
}
};

void spfa(const int s, const int p, Vertex **vertexes)
{
for(int i = 0; i < p; ++i)
{
dis[s][i] = infinity;
}
dis[s][s] = 0;

deque<int> que;
bool onQueue[P];
memset(onQueue, false, p * sizeof(bool));

que.push_back(s);
onQueue[s] = true;

while(!que.empty())
{
int u = que.front();
que.pop_front();
onQueue[u] = false;
for(Edge *e = vertexes[u]->adj; e != NULL; e = e->next)
{
if(dis[s][u] + e->w < dis[s][e->v])
{
dis[s][e->v] = dis[s][u] + e->w;
if(!onQueue[e->v])
{
if(que.empty() || dis[s][e->v] < dis[s][que.front()])
{
que.push_front(e->v);
}
else
{
que.push_back(e->v);
}
onQueue[e->v] = true;
}
}
}
}
}

int main()
{
FILE *fin  = fopen ("butter.in", "r");
FILE *fout = fopen ("butter.out", "w");
//freopen("log_1.txt", "w", stdout);

int n, p, c;
fscanf(fin, "%d%d%d", &n, &p, &c);

Vertex **vertexes = new Vertex*[p];
for(int i = 0; i < p; ++i)
{
vertexes[i] = new Vertex(i);
}

vector<int> dests;
for(int i = 0; i < n; ++i)
{
int dest;
fscanf(fin, "%d", &dest);
dests.push_back(dest - 1);
}

for(int i = 0; i < c; ++i)
{
int p1, p2, d;
fscanf(fin, "%d%d%d", &p1, &p2, &d);

Edge *euv = new Edge(p2 - 1, d);
euv->next = vertexes[p1 - 1]->adj;
vertexes[p1 - 1]->adj = euv;

Edge *evu = new Edge(p1 - 1, d);
evu->next = vertexes[p2 - 1]->adj;
vertexes[p2 - 1]->adj = evu;
}

for(int i = 0; i < n; ++i)
{
spfa(dests[i], p, vertexes);
}

int mindis = -1;
for(int i = 0; i < p; ++i)
{
int sum = 0;
for(int j = 0; j < n; ++j)
{
sum += dis[dests[j]][i];
//fprintf(stdout, "%d->%d: %d, ", i, dests[j], dis[dests[j]][i]);
}
//fprintf(stdout, "\n%d: %d\n\n", i, sum);
if(mindis < 0 || sum < mindis)
{
mindis = sum;
}
}

fprintf(fout, "%d\n", mindis);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: