POJ - 3268 Silver Cow Party
题意
求所有点到终点的最短路和终点到所有点的最短路
的累加和
思路
在有向图中, 求所有点到某点的最短距离, 建立反向图跑单源最短路即可
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 1010;
int g1[N][N];
int g2[N][N];
int dist1[N];
int dist2[N];
int n, m, p;
bool st[N];
void dijkstra(int g[N][N], int dist[N]) {
memset(st, false, sizeof st);
dist[p] = 0;
for(int i = 0; i < n - 1; i ++) {
int t = -1;
for(int j = 1; j <= n; j ++) {
if(!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
}
st[t] = true;
for(int j = 1; j <= n; j ++) {
dist[j] = min(dist[j], dist[t] + g[t][j]);
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m >> p;
memset(g1, 0x3f, sizeof g1);
memset(g2, 0x3f, sizeof g2);
while(m --) {
int a, b, c;
cin >> a >> b >> c;
g1[a][b] = min(g1[a][b], c);
g2[b][a] = min(g2[b][a], c);
}
memset(dist1, 0x3f, sizeof dist1);
memset(dist2, 0x3f, sizeof dist2);
dijkstra(g1, dist1);
dijkstra(g2, dist2);
int ans = 0;
for(int i = 1; i <= n; i ++) {
if(i != p && dist1[i] != 0x3f3f3f3f && dist2[i] != 0x3f3f3f3f) {
ans = max(ans, dist1[i] + dist2[i]);
}
}
cout << ans << endl;
return 0;
}
POJ - 1062 昂贵的聘礼
思路
虚拟源点建图 + 最短路
代码
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int N = 110, INF = 0x3f3f3f3f;
int w[N][N];
int level[N];
int n, m;
bool st[N];
int dist[N];
int dijkstra(int l, int r) {
memset(dist, 0x3f, sizeof dist);
memset(st, false, sizeof st);
dist[0] = 0;
for(int i = 1; i <= n; i ++) {
int t = -1;
for(int j = 0; j <= n; j ++) {
if(!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
}
st[t] = true;
for(int j = 1; j <= n; j ++) {
if(level[j] >= l && level[j] <= r) {
dist[j] = min(dist[j], dist[t] + w[t][j]);
}
}
}
return dist[1];
}
int main() {
cin >> m >> n;
memset(w, 0x3f, sizeof w);
for(int i = 0; i <= n; i ++)
w[i][i] = 0;
for(int i = 1; i <= n; i ++) {
int price, cnt;
cin >> price >> level[i] >> cnt;
w[0][i] = min(w[0][i], price);
while(cnt --) {
int id, cost;
cin >> id >> cost;
w[id][i] = min(w[id][i], cost);
}
}
int res = INF;
for(int i = level[1] - m; i <= level[1]; i ++) {
res = min(res, dijkstra(i, i + m));
}
cout << res << endl;
return 0;
}
POJ2253 Frogger
题意
找出所有路径中最大边是最小的这个路径, 输出这个路径的最大边。
思路
数据小, floyd求解
f
[
i
]
[
j
]
=
m
i
n
(
f
[
i
]
[
j
]
,
m
a
x
(
f
[
i
]
[
k
]
,
f
[
k
]
[
j
]
)
)
f[i][j] = min(f[i][j], max(f[i][k], f[k][j]))
f[i][j]=min(f[i][j],max(f[i][k],f[k][j]))
代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#define sd(x) scanf("%d", &x)
#define rep(i, a, b) for(int i = a; i <= b; i ++)
using namespace std;
const int N = 205;
double g[N][N];
int n, x[N], y[N], time = 0;
void floyd() {
int i, j, k;
rep(i, 1, n)
rep(j, i + 1, n) {
g[i][j] = g[j][i] = sqrt(double(x[i] - x[j])*(x[i] - x[j]) + double(y[i] - y[j])*(y[i] - y[j]));
}
rep(k, 1, n)
rep(i, 1, n)
rep(j, 1, n){
g[i][j] = min(g[i][j], max(g[i][k], g[k][j]));
}
}
int main() {
while(~scanf("%d", &n) && n) {
time ++;
for(int i = 1; i <= n; i ++)
cin >>x[i] >> y[i];
floyd();
printf("Scenario #%d\nFrog Distance = %.3f\n\n", time, g[1][2]);
}
return 0;
}
POJ - 1797 Heavy Transportation
题意
与上题类似,正好相反
找出最小边是最大的路径,输出最小边
思路
这里用djkstra, 其他也行
dist[] 保存路径中最大的 最小边
d
i
s
t
[
j
]
=
m
a
x
(
d
i
s
t
[
j
]
,
m
i
n
(
d
i
s
t
[
v
e
r
]
,
g
[
v
e
r
]
[
j
]
)
dist[j] = max(dist[j], min(dist[ver], g[ver][j])
dist[j]=max(dist[j],min(dist[ver],g[ver][j])
代码
#include<iostream>
#include<cstring>
#include<algorithm>
#define sd(x) scanf("%d", &x)
#define rep(i, a, b) for(int i = a; i <= b; i ++)
#include<queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 1010;
int g[N][N];
int n, m;
int dist[N];
bool st[N];
void dijkstra() {
priority_queue<PII> q;
memset(dist, -0x3f, sizeof dist);
memset(st, false, sizeof st);
dist[1] = 0x3f3f3f3f;
q.push({dist[1], 1});
while(q.size()) {
PII t = q.top(); q.pop();
int ver = t.second;
if(st[ver]) continue;
st[ver] = true;
for(int j = 1; j <= n; j ++) {
if(g[ver][j] && !st[j])
dist[j] = max(dist[j], min(dist[ver], g[ver][j]));
}
}
}
int main() {
int T, id = 0;
sd(T);
while(T --){
memset(g, 0, sizeof g);
int n, m;
sd(n), sd(m);
while(m --) {
int a, b, c;
sd(a), sd(b), sd(c);
g[a][b] = g[b][a] = c;
}
dijkstra();
printf("Scenario #1:\n%d\n\n", ++id, dist[n]);
}
}
POJ - 3660 Cow Contest
题意
找出确定排名的牛的个数
确定排名的条件,比自己小的 + 比自己大的 == n - 1
思路
传递闭包
代码
#include<iostream>
#include<cstring>
#include<algorithm>
#define sd(x) scanf("%d", &x)
#define rep(i, a, b) for(int i = a; i <= b; i ++)
using namespace std;
const int N = 110;
int g[N][N];
int n, m;
void floyd() {
rep(k, 1, n)
rep(i, 1, n)
rep(j ,1, n) {
g[i][j] |= g[i][k] & g[k][j];
}
}
int main() {
cin >> n >> m;
while(m --) {
int a, b;
cin >> a >> b;
g[a][b] = 1;
}
floyd();
int ans = 0;
for(int i = 1; i <= n; i ++) {
int cnt = 0;
for(int j = 1; j <= n; j ++) {
if(g[i][j] || g[j][i]) cnt ++;
}
if(cnt == n - 1) ans ++;
}
cout << ans << endl;
}
HDU - 4725 The Shortest Path in Nya Graph
思路
非常妙的建图
把某层当成虚拟的点编号N+i,防止重复,
它到达它那层的所有点的距离是0
而某一层的点 到自己的上下层虚拟点 的距离是C
参考: 大佬题解
代码
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
const int maxn=2e5+10;
struct Node
{
int to,w;
Mode() {}
Node(int to,int w):to(to),w(w) {}
};
vector<Node> vv[maxn];//用vector表示邻接表
int N,M,C;
int layer[maxn],islayer[maxn];//layer记录第i点所在的层数,islayer记录该层是否有点
int vis[maxn];
int dist[maxn];
struct cmp
{
bool operator()(int a,int b)
{
return dist[a]>dist[b];
}
};
void Dijkstra()
{
priority_queue<int,vector<int>,cmp> pq;
fill(dist,dist+maxn,INF);
fill(vis,vis+maxn,0);
dist[1]=0;
pq.push(1);
while(!pq.empty())
{
int u=pq.top();
pq.pop();
if(vis[u])
continue;
vis[u]=1;
for(int i=0; i<vv[u].size(); i++)
{
int v=vv[u][i].to;
int w=vv[u][i].w;
if(dist[v]>dist[u]+w)
{
dist[v]=dist[u]+w;
pq.push(v);
}
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T,cas=0;
cin>>T;
while(T--)
{
memset(layer,0,sizeof(layer));
memset(islayer,0,sizeof(islayer));
memset(vv,0,sizeof(vv));
cin>>N>>M>>C;
//增点建图
for(int i=1; i<=N; i++)//为每层分配一个点,并把它与所在该层的点相连接
{
cin>>layer[i];
islayer[layer[i]]=1;
}
for(int i=1; i<=N; i++)//给每个点建边
{
vv[layer[i]+N].push_back(Node(i,0));
if(islayer[layer[i]-1])//判断上一层的点是否存在,若存在连接
{
vv[i].push_back(Node(layer[i]-1+N,C));
}
if(islayer[layer[i]+1])//判断下一层的点是否存在,若存在连接
{
vv[i].push_back(Node(layer[i]+1+N,C));
}
}
//插入M条边
for(int i=1; i<=M; i++)
{
int u,v,w;
cin>>u>>v>>w;
vv[u].push_back(Node(v,w));
vv[v].push_back(Node(u,w));
}
Dijkstra();
if(dist[N]!=INF)
cout<<"Case #"<<++cas<<": "<<dist[N]<<endl;
else
cout<<"Case #"<<++cas<<": -1"<<endl;
}
return 0;
}