日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P2446 [SDOI2010]大陆争霸

發(fā)布時間:2023/12/3 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P2446 [SDOI2010]大陆争霸 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

P2446 [SDOI2010]大陸爭霸

題意:

n個點,m個邊,wi為每個邊的邊權(quán),對于每個點i,其被l個點保護著,也就是如果保護其的點沒有被破壞,點i無法被破壞(也無法經(jīng)過其前往其他點)。現(xiàn)在從1出兵(無限數(shù)量),問破壞點n的最短時間

題解:

很明顯這個題跟最短路有關(guān),對于每個點,有這幾種狀態(tài):是否保護,是否已經(jīng)到達
因為如果我們跑最短路,跑出來的結(jié)果并不是,因為有些點受保護的情況,實際到達時間要被推遲(直到保護他的點也被破壞)
我們用now[u]表示點u被破壞的時間,arrive[u]表示u無人保護的時刻(如果一開始就無人保護,默認值為0),dis[u]表示路徑上到達u的時間
對于now[u]應(yīng)該取dis[u]和arrive[u]的最大值,因為u被破壞需要可達(不被保護)且已經(jīng)到達(路徑距離)
dis[u]最短路維護,arrive[u]怎么維護呢?
arrive[u]記錄的其實是保護u的點x,x被破壞的最大值。所以如果u被x保護,我們就從x到u建一個邊(無向邊),在跑最短路過程中,不斷更新arrive[u],arrive[u]=max(now[x])
詳細可以見代碼

代碼:

#include<bits/stdc++.h> #define debug(a,b) printf("%s = %d\n",a,b); using namespace std; typedef long long ll; typedef pair<int, int> PII; clock_t startTime, endTime; //Fe~Jozky const ll INF_ll=1e18; const int INF_int=0x3f3f3f3f; inline ll read(){ll s=0,w=1ll;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w; } void rd_test(){#ifdef ONLINE_JUDGE#elsestartTime = clock(); //計時開始freopen("landcraft.in","r",stdin);#endif } void Time_test(){#ifdef ONLINE_JUDGE#elseendTime = clock(); //計時結(jié)束printf("\n運行時間為:%lfs\n",(double)(endTime - startTime) / CLOCKS_PER_SEC);#endif } const int maxn=1e6+9; struct Edge {int u,v,w,next; }e[maxn]; int head[maxn],cnt,n,m,s,vis[maxn],dis[maxn],pre[maxn]; int ind[maxn],arrive[maxn],now[maxn]; struct node {int w,now;inline bool operator <(const node &x)const//重載運算符把最小的元素放在堆頂(大根堆){return w>x.w;//這里注意符號要為'>'} }; priority_queue<node>q; inline void add(int u,int v,int w) {e[++cnt].u=u;//這句話對于此題不需要,但在縮點之類的問題還是有用的e[cnt].v=v;e[cnt].w=w;e[cnt].next=head[u];//存儲該點的下一條邊head[u]=cnt;//更新目前該點的最后一條邊(就是這一條邊) } vector<int>vec[maxn]; void dijkstra() {for(int i=1;i<=n;i++){dis[i]=INF_int;arrive[i]=0;}dis[s]=arrive[s]=0;//賦初值q.push((node){0,s});int u,v;while(!q.empty())//堆為空即為所有點都更新{node x=q.top();q.pop();u=x.now;//記錄堆頂(堆內(nèi)最小的邊)并將其彈出if(vis[u]) continue; //沒有遍歷過才需要遍歷vis[u]=1;now[u]=max(dis[u],arrive[u]);//到達u的時間時間 for(int i=head[u];i;i=e[i].next)//更新所有dis[v] {v=e[i].v;if(dis[v]>now[u]+e[i].w){dis[v]=now[u]+e[i].w;if(!ind[v]){//如果這個點沒有被保護 pre[v]=u;//松弛操作now[v]=max(dis[v],arrive[v]);q.push((node){max(dis[v],arrive[v]),v});//把新遍歷到的點加入堆中}}}//開始摧毀點u for(int i=0;i<vec[u].size();i++){v=vec[u][i];ind[v]--;arrive[v]=max(arrive[v],now[u]);if(!ind[v]){now[v]=max(dis[v],arrive[v]);q.push((node){now[v],v}); }}} }int main() {rd_test();cin>>n>>m;s=1; for(int i=1;i<=m;i++){int x,y,z;x=read(),y=read(),z=read();add(x,y,z);}for(int i=1;i<=n;i++){int l=read();if(l==0)continue;for(int j=1;j<=l;j++){int x=read(); ++ind[i];vec[x].push_back(i);//vec[i].push_back(x);//add(x,i,0);}}dijkstra();cout<<now[n];//Time_test(); }

總結(jié)

以上是生活随笔為你收集整理的P2446 [SDOI2010]大陆争霸的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。