在一個遙遠的世界裏有兩個國家:位於大陸西端的傑森國和位於大陸東端的克里斯國。兩個國家的人民分別信仰兩個對立的神:傑森國信仰象徵黑暗和毀滅的神曾·布拉澤,而克里斯國信仰象徵光明和永恆的神斯普林·布拉澤。優化
幻想歷8012年1月,傑森國正式宣佈曾·布拉澤是他們惟一信仰的神,同時開始迫害在傑森國的信仰斯普林·布拉澤的克里斯國教徒。ui
幻想歷8012年3月2日,位於傑森國東部小鎮神諭鎮的克里斯國教徒發動起義。spa
幻想歷8012年3月7日,神諭鎮的起義被傑森國大軍以殘酷手段鎮壓。3d
幻想歷8012年3月8日,克里斯國對傑森國宣戰。由數十萬大軍組成的克里斯軍團開至兩國邊境,與傑森軍團對峙。code
幻想歷8012年4月,克里斯軍團攻破傑森軍團防線進入神諭鎮,該鎮倖存的克里斯國教徒獲得解放。blog
戰爭隨後進入膠着狀態,曠日持久。戰況慘烈,一時間槍林彈雨,硝煙瀰漫,民不聊生。get
幻想歷8012年5月12日深夜,斯普林·布拉澤降下神諭:「Trust me, earn eternal life.」克里斯軍團士氣大增。做爲克里斯軍團的主帥,你決定利用這一機會發動奇襲,一舉擊敗傑森國。具體地說,傑森國有N個城市,由M條單向道路鏈接。神諭鎮是城市1而傑森國的首都是城市N。你只需摧毀位於傑森國首都的曾·布拉澤大神殿,傑森國的信仰,軍隊還有一切就都會土崩瓦解,灰飛煙滅。string
爲了儘可能減少己方的消耗,你決定使用自爆機器人完成這一任務。惟一的困難是,傑森國的一部分城市有結界保護,不破壞掉結界就沒法進入城市。而每一個城市的結界都是由分佈在其餘城市中的一些結界發生器維持的,若是想進入某個城市,你就必須破壞掉維持這個城市結界的全部結界發生器。it
如今你有無限多的自爆機器人,一旦進入了某個城市,自爆機器人能夠瞬間引爆,破壞一個目標(結界發生器,或是傑森國大神殿),固然機器人自己也會一塊兒被破壞。你須要知道:摧毀傑森國所需的最短期。io
輸入格式:
輸入文件的landcraft.in的第一行兩個正整數N, M。
接下來M行,每行三個正整數ui, vi, wi,表示有一條從城市ui到城市vi的單向道路,自爆機器人經過這條道路須要wi的時間。
以後N行,每行描述一個城市。首先是一個正整數li,維持這個城市結界所使用的結界發生器數目。以後li個1~N之間的城市編號,表示每一個結界發生器的位置。若是li = 0,則說明該城市沒有結界保護,保證l1 = 0 。
輸出格式:
輸出文件landcraft.out僅包含一個正整數 ,擊敗傑森國所需的最短期。
6 6 1 2 1 1 4 3 2 3 1 2 5 2 4 6 2 5 3 2 0 0 0 1 3 0 2 3 5
5
對於20%的數據,知足N≤15,M≤50;
對於50%的數據,知足N≤500,M≤6,000;
對於100%的數據,知足N≤3,000,M≤70,000,1≤wi≤108。
輸入數據保證必定有解,且不會存在維持某個城市結界的結界發生器在這個城市內部。
鏈接兩個城市的道路可能不止一條,也可能存在一個城市本身到本身的道路。
用dis[i]記錄到i點的路徑距離,dits[i]記錄炸掉i的用時
最短路二者取大
堆優化dijkstra:
1 #include <algorithm> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 6 #define LL long long 7 8 using namespace std; 9 10 const int N(30000+15); 11 const int M(700000+5); 12 int n,m,rd[N],u,v,w; 13 14 int hed[N],had[N],sumedge; 15 struct Edge 16 { 17 int u,v,w,next; 18 Edge(int u=0,int v=0,int w=0,int next=0): 19 u(u),v(v),w(w),next(next){} 20 }edge[M]; 21 void ins(int u,int v,int w,int *head) 22 { 23 edge[++sumedge]=Edge(u,v,w,head[u]); 24 head[u]=sumedge; 25 } 26 27 priority_queue<pair<LL,int>,vector<pair<LL,int> >,greater<pair<LL,int> > >que; 28 LL cost,MAX,dis[N],dist[N]; 29 int fro,vis[N]; 30 void Dijkstra() 31 { 32 memset(dis,0x3f,sizeof(dis)); 33 que.push(make_pair(0,1)); 34 dis[1]=0; 35 while(!que.empty()) 36 { 37 fro=que.top().second; que.pop(); 38 if(vis[fro]) continue; 39 vis[fro]=1; 40 MAX=max(dis[fro],dist[fro]); 41 for(int i=hed[fro];i;i=edge[i].next) 42 { 43 int to=edge[i].v; 44 if(MAX+edge[i].w<dis[to]) 45 { 46 dis[to]=MAX+edge[i].w; 47 cost=max(dis[to],dist[to]); 48 if(!rd[to]) que.push(make_pair(cost,to)); 49 } 50 } 51 for(int i=had[fro];i;i=edge[i].next) 52 { 53 int to=edge[i].v; 54 rd[to]--; 55 dist[to]=max(MAX,dist[to]); 56 cost=max(dis[to],dist[to]); 57 if(!rd[to]) que.push(make_pair(cost,to)); 58 } 59 } 60 } 61 62 int main() 63 { 64 scanf("%d%d",&n,&m); 65 for(;m--;) 66 scanf("%d%d%d",&u,&v,&w),ins(u,v,w,hed); 67 for(int i=1;i<=n;i++) 68 { 69 scanf("%d",&rd[i]); 70 for(int j=1;j<=rd[i];j++) 71 scanf("%d",&v),ins(v,i,0,had); 72 } 73 Dijkstra(); 74 printf("%d\n",max(dis[n],dist[n])); 75 return 0; 76 }