您的位置:首页 > 其它

[USACO Mar08] 牛跑步

2016-12-02 20:24 369 查看
[USACO Mar08] 牛跑步

时间限制:1 s 内存限制:128 MB

BESSIE准备用从牛棚跑到池塘的方法来锻炼. 但是因为她懒,她只准备沿着下坡的路跑到池塘,然后走回牛棚.

BESSIE也不想跑得太远,所以她想走最短的路经. 农场上一共有M (1 <= M <= 10,000)条路,每条路连接两个用1..N(1 <= N <= 1000)标号的地点. 更方便的是,如果X>Y,则地点X的高度大于地点Y的高度. 地点N是BESSIE的牛棚;地点1是池塘.

很快, BESSIE厌倦了一直走同一条路.所以她想走不同的路,更明确地讲,她想找出K (1 <= K <= 100)条不同的路经.为了避免过度劳累,她想使这K条路经为最短的K条路经.

请帮助BESSIE找出这K条最短路经的长度.你的程序需要读入农场的地图, 一些从X_i到Y_i 的路经和它们的长度(X_i, Y_i, D_i). 所有(X_i, Y_i, D_i)满足(1 <= Y_i < X_i; Y_i < X_i <= N, 1 <= D_i <= 1,000,000).

输入格式:

第1行: 3个数: N, M, 和K

第 2..M+1行: 第 i+1 行包含3个数 X_i, Y_i, 和 D_i, 表示一条下坡的路.

样例输入

5 8 7

5 4 1

5 3 1

5 2 1

5 1 1

4 3 4

3 1 1

3 2 1

2 1 1

输出格式:

第1..K行: 第i行包含第i最短路经的长度,或-1如果这样的路经不存在.如果多条路经有同样的长度,请注意将这些长度逐一列出.

样例输出

1

2

2

3

6

7

-1

输出解释:

路径分别为(5-1), (5-3-1), (5-2-1), (5-3-2-1), (5-4-3-1),(5-4-3-2-1).

K短路问题

第一种解法:Dij+A*

#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
namespace cat{
const int maxn = 10000 + 10 ;
void read(int &x){
x=0;char ch;
while(ch=getchar(),ch<'!');
while(x=10*x+ch-'0',ch=getchar(),ch>'!');
}
struct Edge{
int next,to,dis;
}G[maxn<<1];
int head[maxn],from[maxn],to[maxn],dis[maxn];
int val[maxn];
int cnt = 1,n,m,K;
void add(int u,int v,int dis){
G[++cnt].to = v;
G[cnt].dis = dis;
G[cnt].next = head[u];
head[u] = cnt;
}
struct Node{
int num,dist,g,h;
Node(int x,int y){
num=x;dist=y;
}
Node(int x,int y,int z){
num = x;g=y;h=z;
dist = g+h;
}
bool operator < (const Node &x) const {
return dist > x.dist;
}
};
void dijkstra(int s){
priority_queue<Node>Q;
memset(dis,127/3,sizeof(dis));
dis[s] = 0;
Q.push( Node(s,0) );
while(!Q.empty()){
Node t = Q.top();Q.pop();
int x = t.num ;
if( t.dist != dis[t.num] ) continue;
for(int i=head[x];i;i=G[i].next){
if( dis[G[i].to] > dis[x] + G[i].dis ){
dis[G[i].to] = dis[x] + G[i].dis;
Q.push( Node(G[i].to,dis[G[i].to]) );
}
}
}
}
void A_star(int s,int t,int k){
priority_queue<Node>Q;
Q.push( Node(s,0,dis[s]) );
while( !Q.empty() ){
Node x = Q.top();Q.pop();
if( x.num == t ){
printf("%d\n",x.g);
k--;
if( !k ) return;
}
for(int i=head[x.num];i;i=G[i].next){
Q.push(Node(G[i].to,x.g+G[i].dis,dis[G[i].to]));
}
}
for(int i=1;i<=k;i++) printf("-1\n");
return;
}
int doo(){
freopen("cowjog.in","r",stdin);
freopen("cowjog.out","w",stdout);
int k;
read(n);read(m);read(k);
for(int i=1;i<=m;i++){
read(from[i]);read(to[i]);read(val[i]);
add(to[i],from[i],val[i]);
}
int s = n,t = 1;
dijkstra(t);
memset(G,0,sizeof(G));
memset(head,0,sizeof(head));
cnt = 1;
for(int i=1;i<=m;i++){
add(from[i],to[i],val[i]);
}
A_star(s,t,k);
}
}
int ans = cat::doo();
int main(){;}


第二种解法:拓扑排序

#include<cstdio>
#include<queue>
#include<stack>
using namespace std;
priority_queue<int> que[1005];
int n,m,k,ind[1005];
int head[1005],sz=1;
struct E {
int to,w,nxt;
}ed[10005];
void add_edge(int u,int v,int c) {
ed[sz].to=v;
ed[sz].w=c;
ed[sz].nxt=head[u];
head[u]=sz++;
}
stack<int> S;
int tmp[105],t=0;
void topo() {
for (int i=1;i<=n;i++) if (!ind[i]) S.push(i);
que
.push(0);
while (!S.empty()) {
int v=S.top();S.pop();
if (v==1) {
break;
}
t=0;
while (!que[v].empty()) {
tmp[++t]=que[v].top();
que[v].pop();
}
for (int i=head[v];i;i=ed[i].nxt) {
int p=ed[i].to;
for (int j=1;j<=t;j++) {
que[p].push(ed[i].w+tmp[j]);
}
while (que[p].size()>k) {
que[p].pop();
}
if (!--ind[p]) S.push(p);
}
}
int r=k-que[1].size();
t=0;
while (!que[1].empty()) {
tmp[++t]=que[1].top();
que[1].pop();
}
while (t) {
printf("%d\n",tmp[t--]);
}
for (int i=0;i<r;i++) printf("-1\n");
}
int main() {
freopen("cowjog.in","r",stdin);
freopen("cowjog.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
int a,b,c;
for (int i=1;i<=m;i++) {
scanf("%d%d%d",&a,&b,&c);
add_edge(a,b,c);
ind[b]++;
}
topo();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  K短路