标签:输入 包含 vector air pop std bzoj 任务 names
对于 20%的数据,满足 N≤15,M≤50;
对于 50%的数据,满足 N≤500,M≤6,000;
对于 100%的数据,满足 N≤3,000,M≤70,000,1≤wi≤108。
输入数据保证一定有解,且不会存在维持某个城市结界的结界发生器在这个城市内部。
连接两个城市的道路可能不止一条, 也可能存在一个城市自己到自己的道路。
题解:显然这是满足Dijsktra的贪心条件的。
用f[i]表示机器人到达点i的最短时间,用g[i]表示摧毁i的所有结界发生器的最短时间,那么在跑最短路时,用max(f[i],g[i])来更新它所有出边的f值,以及它所有保护的点的g值,如果一个点的所有结界发生器都被摧毁,则将其压入队列。
#include <cstdio> #include <cstring> #include <iostream> #include <vector> #include <queue> #include <utility> #define mp(A,B) make_pair(A,B) using namespace std; const int maxn=3010; typedef long long ll; int n,m,cnt; vector<int> v[maxn]; int vis[maxn],rly[maxn],to[70010],next[70010],head[maxn]; ll d1[maxn],d2[maxn],val[70010]; priority_queue<pair<ll,int> > q; inline void add(int a,int b,int c) { to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++; } inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘) f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+gc-‘0‘,gc=getchar(); return ret*f; } int main() { n=rd(),m=rd(); int i,a,b,c,u; memset(head,-1,sizeof(head)); for(i=1;i<=m;i++) a=rd(),b=rd(),c=rd(),add(a,b,c); memset(d1,0x3f,sizeof(d1)); for(i=1;i<=n;i++) { a=rly[i]=rd(); while(a--) b=rd(),v[b].push_back(i); } d1[1]=d2[1]=0,q.push(mp(0,1)); while(!q.empty()) { u=q.top().second,q.pop(); if(vis[u]) continue; vis[u]=1,d1[u]=max(d1[u],d2[u]); if(u==n) { printf("%lld",d1[u]); return 0; } for(i=head[u];i!=-1;i=next[i]) if(d1[to[i]]>d1[u]+val[i]) { d1[to[i]]=d1[u]+val[i]; if(!rly[to[i]]) q.push(mp(-max(d1[to[i]],d2[to[i]]),to[i])); } for(i=0;i<(int)v[u].size();i++) { d2[v[u][i]]=max(d2[v[u][i]],d1[u]),rly[v[u][i]]--; if(!rly[v[u][i]]) q.push(mp(-max(d1[v[u][i]],d2[v[u][i]]),v[u][i])); } } return 0; }
【BZOJ1922】[Sdoi2010]大陆争霸 Dijkstra
标签:输入 包含 vector air pop std bzoj 任务 names
原文地址:http://www.cnblogs.com/CQzhangyu/p/7670121.html