POJ 1511 Invitation Cards——Dijkstra優先隊列優化+反向建圖

【題目描述】

In the age of television, not many people attend theater performances. Antique Comedians of Malidinesia are aware of this fact. They want to propagate theater and, most of all, Antique Comedies. They have printed invitation cards with all the necessary information and with the programme. A lot of students were hired to distribute these invitations among the people. Each student volunteer has assigned exactly one bus stop and he or she stays there the whole day and gives invitation to people travelling by bus. A special course was taken where students learned how to influence people and what is the difference between influencing and robbery.

The transport system is very special: all lines are unidirectional and connect exactly two stops. Buses leave the originating stop with passangers each half an hour. After reaching the destination stop they return empty to the originating stop, where they wait until the next full half an hour, e.g. X:00 or X:30, where ‘X’ denotes the hour. The fee for transport between two stops is given by special tables and is payable on the spot. The lines are planned in such a way, that each round trip (i.e. a journey starting and finishing at the same stop) passes through a Central Checkpoint Stop (CCS) where each passenger has to pass a thorough check including body scan.

All the ACM student members leave the CCS each morning. Each volunteer is to move to one predetermined stop to invite passengers. There are as many volunteers as stops. At the end of the day, all students travel back to CCS. You are to write a computer program that helps ACM to minimize the amount of money to pay every day for the transport of their employees.
Input
The input consists of N cases. The first line of the input contains only positive integer N. Then follow the cases. Each case begins with a line containing exactly two integers P and Q, 1 <= P,Q <= 1000000. P is the number of stops including CCS and Q the number of bus lines. Then there are Q lines, each describing one bus line. Each of the lines contains exactly three numbers - the originating stop, the destination stop and the price. The CCS is designated by number 1. Prices are positive integers the sum of which is smaller than 1000000000. You can also assume it is always possible to get from any stop to any other stop.
Output
For each case, print one line containing the minimum amount of money to be paid each day by ACM for the travel costs of its volunteers.
Sample Input

2
2 2
1 2 13
2 1 33
4 6
1 2 10
2 1 60
1 3 20
3 4 10
2 4 5
4 1 50

Sample Output

46
210

【題目分析】
求的是從源點到所有點以及所有點到源點的路程和最小,對于源點到所有點的路程和最小我們很自然的想到Dijkstra,因為數據規模比較大需要用鄰接表,我用的是前向星的方式進行儲存,雖然用vector也可以,但是聽說vector更有可能MLE(因為STL中vector實際要多用一倍的空間)和TLE(因為vector的一些挺簡單的操作耗時比一般數組要長)。
但是對于其他所有的點到源點的路程和最小我們直接用Dijkstra顯然是不行的,而用Floyed復雜度太高。
這個時候就需要一點點腦洞想到反向建圖(圖論中反向建圖經常會碰到,很多正面看起來難以解決的問題反過來看就會變的簡單起來),反向建圖后我們再跑一遍Dijkstra,這時候的路徑方向全部反過來就是實際上其他所有點到源點的路徑。然后再求和就可以啦。
前向星進行儲存的時候要注意head數組(保存每個點第一條邊的數組)如果初始化為0,邊一定要從1開始,否則無法判斷到底是沒有邊了還是指向第一個邊,如果習慣從0開始數邊應該將head數組初始化為-1.
將結構體作為優先隊列的元素的時候需要進行運算符重載,優先隊列默認是使用小于號進行比較的,我們應該對小于號進行重載。如果想要按照某個值從大到小重載后還是小于號,如果想要某個值從小到大應該重載為大于號,這是因為優先隊列默認是從大到小的,也就是“重載后值越小”的越在后面。
在對Dijkstra用優先隊列優化的時候不要進行初始化,也不要將源點設置為已經訪問過,如果設為已經訪問過就直接退出了。而將dis數組進行初始化以后我們后面就很有可能沒有辦法將其他節點放入隊列。
【AC代碼】

/*
*因為將兩個過程分別寫出來了顯得有點丑,空間也有點大
*我們也可以兩次建圖,用一套數組就好了
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<climits>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;typedef long long ll;
const int MAXN=1e6+5;
struct node
{int v,next;ll w;node(int _v=0,int _next=0,ll _w=0):v(_v),w(_w),next(_next){}
}Edge1[MAXN],Edge2[MAXN];
struct qnode
{int x; ll d;qnode(int _x=0,ll _d=0):x(_x),d(_d){}bool operator <(const qnode &r)const {return d>r.d;}
}p;
int head1[MAXN],head2[MAXN],tot1,tot2;
bool vis[MAXN];
ll dis1[MAXN],dis2[MAXN],ans;
int n,m;void AddEdge1(int u,int v,ll w)
{tot1++;Edge1[tot1].v=v; Edge1[tot1].w=w; Edge1[tot1].next=head1[u];head1[u]=tot1;
}void AddEdge2(int u,int v,int w)
{tot2++;Edge2[tot2].v=v; Edge2[tot2].w=w; Edge2[tot2].next=head2[u];head2[u]=tot2;
}void Dijkstra1()
{memset(vis,0,sizeof(vis));memset(dis1,0x3f,sizeof(dis1));const int INF=dis1[1];int u,v;// for(int i=head1[1];i;i=Edge1[i].next)// {//     dis1[Edge1[i].v]=Edge1[i].w;// }dis1[1]=0;//vis[1]=true;priority_queue<qnode> q;q.push(qnode(1,0));while(!q.empty()){p=q.top(); q.pop();if(vis[p.x]) continue;vis[p.x]=true;u=p.x;for(int i=head1[u];i;i=Edge1[i].next){v=Edge1[i].v;if(!vis[v]  && dis1[v]>dis1[u]+Edge1[i].w){dis1[v]=dis1[u]+Edge1[i].w;q.push(qnode(v,dis1[v]));}}}
}void Dijkstra2()
{memset(vis,0,sizeof(vis));memset(dis2,0x3f,sizeof(dis2));const int INF=dis2[1];int u,v;// for(int i=head2[1];i;i=Edge2[i].next)// {//     dis2[Edge2[i].v]=Edge2[i].w;// }dis2[1]=0; //vis[1]=true;priority_queue<qnode> q;q.push(qnode(1,0));while(!q.empty()){p=q.top(); q.pop();if(vis[p.x]) continue;vis[p.x]=true;u=p.x;for(int i=head2[u];i;i=Edge2[i].next){v=Edge2[i].v;if(!vis[v] && dis2[v]>dis2[u]+Edge2[i].w){dis2[v]=dis2[u]+Edge2[i].w;q.push(qnode(v,dis2[v]));}}}
}void test()
{for(int i=1;i<=n;i++){printf("%lld ",dis1[i]);}printf("\n");for(int i=1;i<=n;i++){printf("%lld ",dis2[i]);}printf("\n");
}int main()
{int T,u,v; ll w;scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);tot1=0; tot2=0;memset(head1,0,sizeof(head1));memset(head2,0,sizeof(head2));for(int i=0;i<m;i++){scanf("%d%d%lld",&u,&v,&w);AddEdge1(u,v,w); AddEdge2(v,u,w);}Dijkstra1(); Dijkstra2();//test();ans=0;for(int i=1;i<=n;i++){ans+=dis1[i]+dis2[i];}printf("%lld\n",ans);}return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384070.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384070.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384070.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

鏈棧 尹成

http://blog.csdn.net/itcastcpp/article/details/39271661 今天&#xff0c;我們一起用C寫鏈棧&#xff0c;具體如下。 LinkStack.h具體內容&#xff1a; [cpp] view plaincopy #include "StackNode.h" template<typename Type> class LinkStack{ publ…

信號的捕捉以及SIGCHLD信號

一. 信號的捕捉定義 用戶提供一個處理函數, 要求內核在處理信號時必須切換到用戶態,執行這個函數, 這種方式就叫做信號的捕捉 二. 圖解信號的捕捉過程 1. 由上圖可以看出,當處理信號的執行動作時用戶自定義的時候,此時就需返回該函數去調用該函數, 這就叫做信號的捕捉. 以前我…

鏈隊 尹成

http://blog.csdn.net/itcastcpp/article/details/39271691 今天&#xff0c;我們一起用C寫一個鏈對&#xff0c;具體如下所示。 LinkQueue.h具體內容如下&#xff1a; [cpp] view plaincopy #include "QueueNode.h" template<typename Type> class LinkQueu…

強連通分量入門——Trajan算法

今天學習了強連通分量。 【參考博客】 如果覺得我講的有些地方難以理解或者存在問題&#xff08;歡迎留言&#xff09;&#xff0c;可以看一下我借鑒的一些大佬的博客&#xff1a; 傳送門1 傳送門2 【知識儲備】 首先我們需要對幾個定義有一些概念&#xff1a; 強連通&#xff…

最小棧的實現

所謂最小棧, 就是當前棧頂元素最小, 我們可以這樣做, 每次在入棧之前, 將待入棧元素與棧頂元素相比, 每次現將待入棧的元素先入棧, 再將帶入棧的元素和較小的元素入棧, 這樣就可以保證每次棧頂元素是最小元素. 在出棧的時候規定每次出棧兩個元素,這樣就可以保證在出棧之后棧頂元…

用C++實現單鏈表的創建、逆置和輸出 的兩種方法

http://blog.csdn.net/lfeng_coding/article/details/47300563 題目描述&#xff1a;在已知單鏈表頭節點的情況下&#xff0c;設計算法逆置單鏈表并輸出 方法一&#xff1a;采用首先將頭節點指向空&#xff0c;讓其變為尾節點&#xff0c;然后利用中間節點 p、q 將其后的節點一…

兩個棧實現一個隊列

利用兩個棧實現一個隊列思路是這樣的. 首先這個隊列包含兩個棧, 然后一個棧用來入隊列, 一個棧用來出隊列 typedef struct QueBy2Stack {SeqStack input;SeqStack output; }QueBy2Stack; 1. 初始化 void QueBy2StackInit(QueBy2Stack* stack) {if(stack NULL){return;//非法…

HDU 5934:Boom——強連通分量+縮點

【題目描述】 There are N bombs needing exploding.Each bomb has three attributes: exploding radius ri, position (xi,yi) and lighting-cost ci which means you need to pay ci cost making it explode.If a un-lighting bomb is in or on the border the exploding ar…

Linux--線程死鎖

http://blog.csdn.net/gebushuaidanhenhuai/article/details/73799824 線程為什會死鎖&#xff1f;&#xff1f;“鎖”又是什么東西&#xff1f;我們這篇博客主要講一下為什么要給線程加鎖&#xff0c;為什么會出現線程死鎖&#xff0c;線程死鎖怎么解決。 互斥鎖 在我的上篇博…

兩個隊列實現一個棧

用兩個隊列實現一個棧的原理是這樣的. 規定兩個隊列, 必須有一個隊列是非空, 一個隊列是空.每次入棧時必須往非空隊列中入, 而每次出棧時, 必須將非空隊列里的元素裝到空隊列中, 直到非空隊列中只有一個元素時, 此時就將剩下的這個元素出棧即可. 而取棧頂元素時, 和出棧一樣, 先…

POJ-1144 Network——Trajan+割點

【題目描述】 A Telephone Line Company (TLC) is establishing a new telephone cable network. They are connecting several places numbered by integers from 1 to N . No two places have the same number. The lines are bidirectional and always connect together tw…

Linux--生產者與消費者

http://blog.csdn.net/gebushuaidanhenhuai/article/details/74011636 基本概念 提到生產者和消費者&#xff0c;我們最有可能想到的是商店賣東西&#xff0c;顧客在貨架上(緩沖區&#xff09;買東西。 生產者消費者問題&#xff0c;其實是一個多線程同步問題的經典案例。該問…

進程的掛起以及可重入函數

相關接口 ????pause 函數用于將進程掛起. 如果信號的處理動作是終止進程, 則進程終止, pause 函數沒有返回值; 如果信號的處理動作是忽略, 則進程被掛起, pause函數不返回, 如果信號的處理動作是捕捉, 則調用信號處理動作之后pause 返回 -1.來看一段代碼 #include<s…

POJ1236Network of Schools——強連通分量縮點建圖

【題目描述】 A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes software (the “receiving schools”). Note that if B is in the distri…

C——通過調用函數分配內存

http://blog.csdn.net/u012627502/article/details/3579724 1&#xff09;以返回值方式返回&#xff1a;把動態分配的存儲位置地址&#xff0c;賦值給指針類型返回值&#xff08;不同于被調用函數的自動變量地址&#xff09; 2&#xff09;以形參形式返回&#xff1a;二級指針類…

gdb調試多進程程序

1.gdb下調試多進程程序只需要以下幾條命令即可 ???????? ????除此之外還可以查看正在調試的進程 info inferiors, 同時也可以將當前正在調試的進程切換到另外一個進程中讓其取運行 ????2.代碼調試演示 #include<stdio.h> #include<stdlib.h> #…

BZOJ1123-BLO——強連通分量求割點+計數

【題目描述】 Byteotia城市有n個 towns m條雙向roads. 每條 road 連接 兩個不同的 towns ,沒有重復的road. 所有towns連通。Input 輸入n<100000 m<500000及m條邊Output 輸出n個數&#xff0c;代表如果把第i個點去掉&#xff0c;將有多少對點不能互通。Sample Input 5…

關于memcpy和memmove兩函數的區別

http://blog.csdn.net/caowei840701/article/details/8491836 [cpp] view plaincopy <p> 關于memcpy和memmove兩個c標準庫函數&#xff0c;其功能都是將一塊內存區域中的指定大小內容復制到目標內存中&#xff0c;在翻閱c標準庫實現的源代碼我們發現他們是有區別的。&…

判斷字符串出棧合法性

先來看說一下思路 接下來就是寫代碼了 int StackOrder(SeqStack* stack, char* input, char* output, int size_input, int size_output) {if(stack NULL || input NULL || output NULL){return 0;}int i_input 0;int j_output 0;SeqStackType value;for(; j_output <…

CodeForces - 1200C——小模擬

【題目描述】 Amugae is in a very large round corridor. The corridor consists of two areas. The inner area is equally divided by n sectors, and the outer area is equally divided by m sectors. A wall exists between each pair of sectors of same area (inner o…