A - Til the Cows Come Home
最短路模板,从终点到起点,双向建边
/***********************************************
* Author: fisty
* Created Time: 2015/1/28 20:55:21
* File Name : 4_A.cpp
*********************************************** */
#include <iostream>
#include <cstring>
#include <deque>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <algorithm>
using namespace std;
#define Debug(x) cout << #x << " " << x <<endl
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef pair<int, int> P;
#define MAX_N 2000
int T, N;
struct node{
int to;
int cost;
node(int _to, int _cost) : to(_to), cost(_cost){}
};
vector<node> G[MAX_N];
int d[MAX_N];
int dijsktra(){
d[N] = 0;
priority_queue<P , vector<P>, greater<P> > que;
que.push(P(d[N], N));
while(que.size()){
P q = que.top(); que.pop();
int v = q.second;
if(d[v] < q.first) continue;
for(int i = 0;i < G[v].size(); i++){
node &e = G[v][i];
if(d[e.to] > d[v] + e.cost){
d[e.to] = d[v] + e.cost;
que.push(P(d[e.to], e.to));
}
}
}
return d[1];
}
int main() {
//freopen("in.txt", "r", stdin);
cin.tie(0);
ios::sync_with_stdio(false);
cin >> T >> N;
memset(d, 0x3f, sizeof(d));
for(int i = 0;i < T; i++){
//构图
int u, v, cost;
cin >> u >> v >> cost;
G[u].push_back(node(v, cost));
G[v].push_back(node(u, cost));
}
int ans = dijsktra();
cout << ans << endl;
return 0;
}
B -Frogger
题目大意:
给出两只青蛙的坐标A、B,和其他的n-2个坐标,任一两个坐标点间都是双向连通的。显然从A到B存在至少一条的通路,每一条通路的元素都是这条通路中前后两个点的距离,这些距离中又有一个最大距离。
现在要求求出所有通路的最大距离,并把这些最大距离作比较,把最小的一个最大距离作为青蛙的最小跳远距离。
Floyd算法
用Floyd算法求出两两最短路,再求出从每个点开始的最长路,最后从这n个最长路中求出最小的那个即为所求。
/***********************************************
* Author: fisty
* Created Time: 2015/1/29 10:55:02
* File Name : 4_B.cpp
*********************************************** */
#include <iostream>
#include <cstring>
#include <deque>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <algorithm>
using namespace std;
#define Debug(x) cout << #x << " " << x <<endl
typedef long long LL;
typedef pair<double, int> PII;
#define MAX_N 210
int N;
double G[MAX_N][MAX_N];
struct Point{
double x, y;
}P[MAX_N];
double solve(){
for(int k = 0;k < N; k++){
for(int i = 0;i < N-1; i++){
for(int j = i+1; j < N; j++){
if(G[i][k] < G[i][j] && G[k][j] < G[i][j]){
G[j][i] = G[i][j] = max(G[i][k], G[k][j]);
}
}
}
}
return G[0][1];
}
int main() {
//freopen("in.txt", "r", stdin);
//cin.tie(0);
//ios::sync_with_stdio(false);
int cnt = 1;
while(~scanf("%d", &N)){
if(!N) break;
printf("Scenario #%d\n", cnt++);
for(int i = 0;i < N; i++){
scanf("%lf%lf", &P[i].x, &P[i].y);
}
for(int i = 0;i < N-1; i++){
for(int j = i+1; j < N; j++){
double x = P[i].x - P[j].x;
double y = P[i].y - P[j].y;
double cost = sqrt(x*x + y*y);
G[i][j] = G[j][i] = cost;
}
}
double ans = solve();
printf("Frog Distance = %.3f\n\n", ans);
}
return 0;
}
C - Heavy Transportation
和上个题要求的正好相反,求最短路径的一条边最小承载量,这里出发点要特殊处理,因为d[s] = 0;之后的点只要d[v] < d[u] && d[v] < cost就可用d[v] = min(d[u], cost)来推了,用的dijsktra,Floyd会超时
/***********************************************
* Author: fisty
* Created Time: 2015/1/30 11:03:39
* File Name : 4_C.cpp
*********************************************** */
#include <iostream>
#include <cstring>
#include <deque>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <algorithm>
using namespace std;
#define Debug(x) cout << #x << " " << x <<endl
typedef long long LL;
typedef pair<int, int> P;
#define MAX_N 1010
int N, M;
struct edge{
int to;
int cost;
edge(int _to ,int _cost) :to(_to), cost(_cost){}
};
vector<edge> G[MAX_N];
int d[MAX_N];
int vis[MAX_N];
int solve(){
memset(d, 0, sizeof(d));
memset(vis, 0, sizeof(vis));
d[1] = 0;
priority_queue <int> que;
for(int i = 0; i < G[1].size(); i++){
//先处理起点,因为与后面不一样
edge e = G[1][i];
d[e.to] = e.cost;
que.push(e.to);
}
//dijsktra
while(que.size()){
int v = que.top(); que.pop();
for(int i = 0;i < G[v].size(); i++){
edge e = G[v][i];
if(d[e.to] < min(d[v], e.cost)){
//同时小于边和上一个顶点时,才能更新
d[e.to] = min(d[v], e.cost);
que.push(e.to);
}
}
}
return d[N];
}
int main() {
//freopen("in.txt", "r", stdin);
//cin.tie(0);
//ios::sync_with_stdio(false);
int cnt = 1;
int t;
scanf("%d", &t);
while(t--){
scanf("%d%d", &N, &M);
printf("Scenario #%d:\n", cnt++);
memset(G, 0, sizeof(G));
for(int i = 0;i < M; i++){
int a, b, cost;
scanf("%d%d%d", &a, &b, &cost);
G[a].push_back(edge(b, cost));
G[b].push_back(edge(a, cost));
}
int ans = solve();
printf("%d\n\n", ans);
}
return 0;
}
<span style="font-size:24px;color:#FF0000;">
</span>
D -
Silver Cow Party
1.求i( 1<= i <=n)到X的最短路径,保存在d_1[i]
2.求X到所有i(1 <= i <= n)的最短路,保存在d_2[i]
3求一条最长的最短路 ans = max(ans, d_1[i] + d_2[i]) (1 <= i <= n)
/***********************************************
* Author: fisty
* Created Time: 2015/1/30 17:51:30
* File Name : 4_D.cpp
*********************************************** */
#include <iostream>
#include <cstring>
#include <deque>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <algorithm>
using namespace std;
#define Debug(x) cout << #x << " " << x <<endl
#define MAX_N 1100
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef pair<int, int> P;
struct edge{
int to;
int cost;
edge(int _to, int _cost) : to(_to), cost(_cost){}
};
vector<edge> G[MAX_N];
int n, M ,X;
int d[MAX_N];
int d_1[MAX_N], d_2[MAX_N]; //去和回
int solve(){
//memset(d_1, 0, sizeof(d_1));
//memset(d_2, 0, sizeof(d_2));
for(int i = 1;i <= n; i++){
int s = i; //出发点
//从各个地方出发到X
if(i == X) continue;
priority_queue<P, vector<P>, greater<P> > que;
memset(d, 0x3f, sizeof(d));
d[s] = 0;
que.push(P(d[s], s));
while(que.size()){
P q = que.top(); que.pop();
int v = q.second;
if(d[v] < q.first) continue;
for(int j = 0;j < G[v].size(); j++){
edge e = G[v][j];
if(d[e.to] > d[v] + e.cost){
d[e.to] = d[v] + e.cost;
que.push(P(d[e.to], e.to));
}
}
}
d_1[i] = d[X];
//Debug(d[X]);
}
//从X出发到各地
priority_queue<P, vector<P>, greater<P> > que;
memset(d, 0x3f, sizeof(d));
d[X] = 0;
que.push(P(d[X], X));
while(que.size()){
P q = que.top(); que.pop();
int v = q.second;
if(d[v] < q.first) continue;
for(int i = 0;i < G[v].size(); i++){
edge e = G[v][i];
if(d[e.to] > d[v] + e.cost){
d[e.to] = d[v] + e.cost;
que.push(P(d[e.to], e.to));
}
}
}
for(int i = 1; i <= n; i++){
if(i == X) continue;
d_2[i] = d[i];
//Debug(d[i]);
}
//求一条最长的最短路
int ans = -INF;
for(int i = 1; i <= n; i++){
if(i == X) continue;
ans = max(ans, d_1[i] + d_2[i]);
}
return ans;
}
int main(){
//freopen("in.txt", "r", stdin);
cin.tie(0);
ios::sync_with_stdio(false);
cin >> n >> M >> X;
for(int i = 0;i < M; i++){
int a, b, cost;
cin >> a >> b >> cost;
//单向
G[a].push_back(edge(b, cost));
}
int ans = solve();
cout << ans << endl;
return 0;
}
E - Currency Exchange
题目大意有多种汇币,汇币之间可以交换,这需要手续费,当你用100A币交换B币时,A到B的汇率是29.75,手续费
是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。问s币的金额经过交换最终得到的s币金额数能否增加
货币的交换是可以重复多次的,所以我们需要找出是否存在正权回路,且最后得到的s金额是增加的
怎么找正权回路呢?(正权回路:在这一回路上,顶点的权值能不断增加即能一直进行松弛)