P2446 [SDOI2010]大陆争霸
生活随笔
收集整理的這篇文章主要介紹了
P2446 [SDOI2010]大陆争霸
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
P2446 [SDOI2010]大陸爭霸
題意:
n個點,m個邊,wi為每個邊的邊權,對于每個點i,其被l個點保護著,也就是如果保護其的點沒有被破壞,點i無法被破壞(也無法經過其前往其他點)。現在從1出兵(無限數量),問破壞點n的最短時間
題解:
很明顯這個題跟最短路有關,對于每個點,有這幾種狀態:是否保護,是否已經到達
因為如果我們跑最短路,跑出來的結果并不是,因為有些點受保護的情況,實際到達時間要被推遲(直到保護他的點也被破壞)
我們用now[u]表示點u被破壞的時間,arrive[u]表示u無人保護的時刻(如果一開始就無人保護,默認值為0),dis[u]表示路徑上到達u的時間
對于now[u]應該取dis[u]和arrive[u]的最大值,因為u被破壞需要可達(不被保護)且已經到達(路徑距離)
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(); //計時結束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;//記錄堆頂(堆內最小的邊)并將其彈出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(); }總結
以上是生活随笔為你收集整理的P2446 [SDOI2010]大陆争霸的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P3293 [SCOI2016]美味
- 下一篇: 工作邮件和工作信息的写作技巧电子邮件写作