(堆)poj3268-Silver Cow Party
先是堆排练练手。
堆排序
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100000;
const int INF = 0x7fffffff;
struct BinaryHeap{
int heap[MAXN], id[MAXN], pos[MAXN], n, counter;
BinaryHeap() : n(0), counter(0) {}
BinaryHeap(int array[], int offset) : n(0), counter(0) {
for (int i = 0; i < offset; ++i) {
heap[++n] = array[i];
pos[n] = id[n] = n;
}
for (int i = n/2; i >= 1; --i) {
down(i);
}
}
void push(int v) {
heap[++n] = v;
id[n] = ++counter;
pos[id[n]] = n;
up(n);
}
int pop() {
swap(heap[1], heap[n]);
swap(id[1], id[n--]);
pos[id[1]] = 1;
down(1);
return id[n+1];
}
int top() {
return heap[1];
}
void up(int i) {
int x = heap[i], y = id[i];
for (int j = i/2; j >= 1; j /= 2) {
if (heap[j] < x) {
heap[i] = heap[j];
id[i] = id[j];
pos[id[i]] = i;
i = j;
}
else {
break;
}
}
heap[i] = x;
id[i] = y;
pos[y] = i;
}
void down(int i) {
int x = heap[i], y = id[i];
for (int j = i*2; j <= n; j *= 2) {
j += j < n && heap[j] < heap[j+1];
if (heap[j] > x) {
heap[i] = heap[j];
id[i] = id[j];
pos[id[i]] = i;
i = j;
}
else {
break;
}
}
heap[i] = x;
id[i] = y;
pos[y] = i;
}
void erase() {
n = 0;
}
bool isEmpty() {
return n == 0;
}
}pq;
int a[MAXN];
int main()
{
freopen("in.txt", "r", stdin);
int n;
cin>>n;
for (int i = 0; i < n; ++i) cin>>a[i];
pq = BinaryHeap(a, n);
while (!pq.isEmpty()) {
cout<<pq.top()<<" ";
pq.pop();
}
return 0;
}
这道题是裸的最短路。为了联系堆,我们用Dijkstra实现。
手写堆实现(64ms)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int INF = 0x7fffffff;
const int MAXN = 2000;
const int MAXM = 100000 + 10;
struct Edge{
int t, w;
Edge(int a=0, int b=0) : t(a), w(b) {}
bool operator < (const Edge& x) const{
return w < x.w;
}
};
vector<Edge> map[MAXN];
struct BinaryHeap{
Edge heap[MAXN];
int n;
BinaryHeap() : n(0) {}
void push(Edge v) {
heap[++n] = v;
up(n);
}
Edge top() {
return heap[1];
}
void pop() {
swap(heap[1], heap[n--]);
down(1);
}
void up(int i) {
Edge x = heap[i];
for (int j = i/2; j >= 1; j /= 2) {
if (x < heap[j]) {
heap[i] = heap[j];
i = j;
}
else {
break;
}
}
heap[i] = x;
}
void down(int i) {
Edge x = heap[i];
for (int j = i*2; j <= n; j *= 2) {
j += j < n && heap[j+1] < heap[j];
if (heap[j] < x) {
heap[i] = heap[j];
i = j;
} else {
break;
}
}
heap[i] = x;
}
bool empty() {
return n == 0;
}
}q;
void Dijkstra(int x, int dis[], int n) {
for (int i = 1; i <= n; ++i) dis[i] = INF;
dis[x] = 0;
q = BinaryHeap();
q.push(Edge(x, 0));
while (!q.empty()) {
Edge now = q.top();
q.pop();
for (int i = 0; i < map[now.t].size(); ++i) {
int to = map[now.t][i].t;
if (dis[to] < dis[now.t] + map[now.t][i].w) continue;
dis[to] = dis[now.t] + map[now.t][i].w;
q.push(Edge(to, dis[to]));
}
}
}
int a[MAXM], b[MAXM], t[MAXM], dis1[MAXN], dis2[MAXN];
int main()
{
freopen("in.txt", "r", stdin);
int n, m, x;
scanf("%d%d%d", &n, &m, &x);
for (int i = 1; i <= m; ++i) {
scanf("%d%d%d", &a[i], &b[i], &t[i]);
map[a[i]].push_back(Edge(b[i], t[i]));
}
Dijkstra(x, dis1, n);
for (int i = 1; i <= n; ++i) {
map[i].clear();
}
for (int i = 1; i <= m; ++i) {
map[b[i]].push_back(Edge(a[i], t[i]));
}
Dijkstra(x, dis2, n);
int ans = 0;
for (int i = 1; i <= n; i++)
if (i != x)
ans = max(dis1[i] + dis2[i], ans);
printf("%d", ans);
return 0;
}
priority_queue实现(32ms)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int INF = 0x7fffffff;
const int MAXN = 2000;
const int MAXM = 100000 + 10;
struct Edge{
int t, w;
Edge(int a=0, int b=0) : t(a), w(b) {}
bool operator < (const Edge& x) const{
return w > x.w;
}
};
priority_queue<Edge> q;
vector<Edge> map[MAXN];
void Dijkstra(int x, int dis[], int n) {
for (int i = 1; i <= n; ++i) dis[i] = INF;
dis[x] = 0;
q.push(Edge(x, 0));
while (!q.empty()) {
Edge now = q.top();
q.pop();
for (int i = 0; i < map[now.t].size(); ++i) {
int to = map[now.t][i].t;
if (dis[to] < dis[now.t] + map[now.t][i].w) continue;
dis[to] = dis[now.t] + map[now.t][i].w;
q.push(Edge(to, dis[to]));
}
}
}
int a[MAXM], b[MAXM], t[MAXM], dis1[MAXN], dis2[MAXN];
int main()
{
freopen("in.txt", "r", stdin);
int n, m, x;
scanf("%d%d%d", &n, &m, &x);
for (int i = 1; i <= m; ++i) {
scanf("%d%d%d", &a[i], &b[i], &t[i]);
map[a[i]].push_back(Edge(b[i], t[i]));
}
Dijkstra(x, dis1, n);
for (int i = 1; i <= n; ++i) {
map[i].clear();
}
for (int i = 1; i <= m; ++i) {
map[b[i]].push_back(Edge(a[i], t[i]));
}
Dijkstra(x, dis2, n);
int ans = 0;
for (int i = 1; i <= n; i++)
if (i != x)
ans = max(dis1[i] + dis2[i], ans);
printf("%d", ans);
return 0;
}
附:堆的基本操作。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int MAXN = 100000;
const int INF = 0x7fffffff;
struct BinaryHeap{
int heap[MAXN], id[MAXN], pos[MAXN], n, counter;
//将数组中的元素按顺序插入所构建的堆
BinaryHeap() : n(0), counter(0) {}
BinaryHeap(int array[], int offset) : n(0), counter(0) {
for (int i = 0; i < offset; ++i) {
heap[++n] = array[i];
pos[i] = id[i] = n;
}
for (int i = n/2; i >= 1; --i) {
down(i);
}
}
void push(int v) {
heap[++n] = v;
id[n] = ++counter;
pos[counter] = n;
up(n);
}
int top() {
return heap[1];
}
int pop() {
swap(heap[1], heap[n]);
swap(id[1], id[n--]);
pos[id[1]] = 1;
down(1);
return id[n+1];
}
int get(int i) {
return heap[pos[i]];
}
void change(int i, int value) {
heap[pos[i]] = value;
down(pos[i]);
up(pos[i]);
}
void erase(int i) {
heap[pos[i]] = INF;
up(pos[i]);
pop();
n--;
}
void up(int i) {
int x = heap[i], y = id[i];
for (int j = i/2; j >= 1; j /= 2) {
if (heap[j] < x) {
heap[i] = heap[j];
id[i] = id[j];
pos[id[i]] = j;
i = j;
} else {
break;
}
}
heap[i] = x;
id[i] = y;
pos[y] = i;
}
void down(int i) {
int x = heap[i], y = id[i];
for (int j = i*2; j <= n; j *= 2) {
j += j < n && heap[j+1] > heap[j];
if (heap[j] > x) {
heap[i] = heap[j];
id[i] = id[j];
pos[id[i]] = i;
i = j;
}
else {
break;
}
}
heap[i] = x;
id[i] = y;
pos[y] = i;
}
bool empty() {
return n == 0;
}
int size() {
return n;
}
void print() {
for (int i = 1; i <= n; i++) cout<<heap[i]<<" ";
cout<<endl;
}
}priorityQueue;
int a[MAXN];
int main()
{
freopen("in.txt", "r", stdin);
int n;
cin>>n;
for (int i = 0; i < n; i++)
cin>>a[i];
//build
cout<<"Build"<<endl;
priorityQueue = BinaryHeap(a, n);priorityQueue.print();
//insert
cout<<"Insert"<<endl;
priorityQueue.push(56);priorityQueue.print();
priorityQueue.push(278);priorityQueue.print();
//top
cout<<"top"<<endl;
cout<<priorityQueue.top()<<endl;;
//pop
cout<<"pop"<<endl;
cout<<priorityQueue.pop()<<endl;
//get
cout<<"get"<<endl;
cout<<priorityQueue.get(2)<<endl;
//change
cout<<"change"<<endl;
priorityQueue.change(2, 3000);priorityQueue.print();
//erase
cout<<"erase"<<endl;
priorityQueue.erase(2);priorityQueue.print();
return 0;
}