POJ--1062--昂貴的聘禮【dijkstra_heap+枚舉】最短路

來源:互聯網
上載者:User

標籤:最短路

連結:http://poj.org/problem?id=1062

題意不說了,中文的


“但是如果他和某個地位較低的人進行了交易,地位較高的的人不會再和他交易,他們認為這樣等於是間接接觸,反過來也一樣。” 這句話一開始沒懂,看discuss裡說的之後才明白,實際上你能交易的等級範圍為 l[i]~l[i]+m,或者l[i]-m~l[i],其中l[i]是第i個人的等級,m是等級差距限制。

這道題建圖,如果對於第 i 個人來說,j 可以通過物品 + t 來交易第 i 個人的物品,則在他們之間建一條有向路徑,方向 j → i ,權值 t ,然後新增一個節點0,從0到任何一點都有一條單向路徑,權值為那一點本身的價值。我們要做的就是從0點出發,找到到達1點的最小值,即dist[1]。

但是等級限制是個問題,剛開始沒想到,看了別人的解題報告,大部分人是枚舉,以第i個人的等級為上限(也可以為下限),如果剩下的人裡有等級比他高的,就標記為已訪問,如果有等級比他低的超過了m的,也標記為已訪問,找最短路時就不做處理。然後枚舉以這n個人的等級為最大值的最短路情況,找到最小的dist[1]。

需要注意的是:

1. 每次標記時會標記vis數組1~n的值,但是不會標記0,0需要自己手動標記,因為這個WA了一發。

2. 還有就是dijkstra_heap的優先隊列裡,找到鄰接表比較路徑長度時沒有判斷出邊的點是否已訪問,因為前幾次都沒加所以也沒有注意,WA了一發,直到發現discuss裡有組資料過不了:

1 5
10000 3 3
2 8000
3 5000
5 1000
1000 2 1
4 200
3000 2 1
4 200
50 2 0
50 6 0

正解是5250。方式為4→3→1。

而我的輸出是1050,因為枚舉第五個人的時候,其他四個由於不符合等級限制都被標記了已訪問,但是0沒被訪問,0還是走一遍,發現5未被標記,5也入隊,由於判斷裡沒有判斷出邊的點是否已訪問,5→1直接更新了dist[1],然後1入隊,發現1已訪問,才退出,但是此時dist[1]的值已是1050,所以得到了錯誤的答案。解決方案就是多加一個是否已訪問的判斷。

#include<cstring>#include<string>#include<fstream>#include<iostream>#include<iomanip>#include<cstdio>#include<cctype>#include<algorithm>#include<queue>#include<map>#include<set>#include<vector>#include<stack>#include<ctime>#include<cstdlib>#include<functional>#include<cmath>using namespace std;#define PI acos(-1.0)#define MAXN 100100#define eps 1e-7#define INF 0x7FFFFFFF#define seed 131#define ll long long#define ull unsigned ll#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1struct node{    int u,v,next;}edge[10100];struct NODE{    int u,dis;    bool operator < (const NODE &t) const{        return t.dis<dis;    }};int vis[110],dist[110],head[110];int n,m,cnt,p[110],l[110];void add_edge(int a,int b,int c){    edge[cnt].u = b;    edge[cnt].v = c;    edge[cnt].next = head[a];    head[a] = cnt++;}void dijkstra_heap(){    int i,j;    NODE t1,t2;    for(i=0;i<=n;i++)   dist[i] = INF;    dist[0] = 0;    vis[0] = 0;    t1.u = 0;    t1.dis = 0;    priority_queue<NODE>q;    q.push(t1);    while(!q.empty()){        t1 = q.top();        q.pop();        if(vis[t1.u])   continue;        vis[t1.u] = 1;        for(i=head[t1.u];i!=-1;i=edge[i].next){            int x = edge[i].v;            if(!vis[edge[i].u]&&dist[t1.u]+x<dist[edge[i].u]){  //沒判斷!vis[edge[i].u] WA出翔                dist[edge[i].u] = dist[t1.u] + x;                t2.u = edge[i].u;                t2.dis = dist[edge[i].u];                q.push(t2);            }        }    }}int main(){    int i,j,x,a,b;    while(scanf("%d%d",&m,&n)!=EOF){        memset(head,-1,sizeof(head));        memset(vis,0,sizeof(vis));        cnt = 0;        for(i=1;i<=n;i++){            scanf("%d%d%d",&p[i],&l[i],&x);            while(x--){                scanf("%d%d",&a,&b);                add_edge(a,i,b);            }        }        for(i=1;i<=n;i++){            add_edge(0,i,p[i]);        }        int minm = INF;        for(i=1;i<=n;i++){            int mm = l[i];            for(j=1;j<=n;j++){                if(l[j]>mm||mm-l[j]>m)  vis[j] = 1;                else    vis[j] = 0;                //cout<<i<<" "<<vis[j]<<endl;            }            dijkstra_heap();            if(dist[1]<minm)    minm = dist[1];        }        printf("%d\n",minm);    }    return 0;}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.