[SDOI2010] BZOJ 1922 大陆争霸-图论-最短路径-dijkstra算法
2017-04-14 21:14
465 查看
题目链接:右转进入题目
题目大意:给定一张有向带权图,但是到达一个点之前必须访问另一些点。
求从点1到点n的最短路径。
题解:
用一个“伪状态转移方程”来描述(之所以是说伪,是因为这是个图而不是个树,所以仅仅用来表示逻辑)
dist[x]=max{d[from[x]],min{dist[pre[x]]+e[i].wgt}}。
这个意思是:到达一个点的真正用时,是在到达它之前必须到达的点的用时的最大值,和所有到达它路径中最短的那一条的最小值取最大值。
说的好乱,最好画个图,例如原题中的图,以第六个点为例,
首先要保证3和5都被访问过了,因此取最大值;
同时要计算出访问4的真正时间再+wgt(4,6)。
然后这二者求个最大值就好了,我觉得到这为止应该就比较明白了。
然后好像由于代码写得太丑并没有用堆优化也过了(复杂度O(n^2+m))。
代码如下(注:d[x]表示访问存储x的结界发生器的城市的最大值,dist[x]则表示访问x的前驱结点的最小值,
辣么说答案就是max{d
,dist
}辣!):
题目大意:给定一张有向带权图,但是到达一个点之前必须访问另一些点。
求从点1到点n的最短路径。
题解:
用一个“伪状态转移方程”来描述(之所以是说伪,是因为这是个图而不是个树,所以仅仅用来表示逻辑)
dist[x]=max{d[from[x]],min{dist[pre[x]]+e[i].wgt}}。
这个意思是:到达一个点的真正用时,是在到达它之前必须到达的点的用时的最大值,和所有到达它路径中最短的那一条的最小值取最大值。
说的好乱,最好画个图,例如原题中的图,以第六个点为例,
首先要保证3和5都被访问过了,因此取最大值;
同时要计算出访问4的真正时间再+wgt(4,6)。
然后这二者求个最大值就好了,我觉得到这为止应该就比较明白了。
然后好像由于代码写得太丑并没有用堆优化也过了(复杂度O(n^2+m))。
代码如下(注:d[x]表示访问存储x的结界发生器的城市的最大值,dist[x]则表示访问x的前驱结点的最小值,
辣么说答案就是max{d
,dist
}辣!):
//SDOI 2010 //BZOJ 1922 #inclu eb08 de<iostream> #include<cstdio> #include<cstring> #include<vector> #include<climits> #define MAXN 3010 #define MAXM 70010 #define INF LLONG_MAX #define ull unsigned long long int using namespace std; struct edge{ int from,to,wgt,pre; }e[MAXM]; int h[MAXN],cnt[MAXN],etop,n,m; ull dist[MAXN],d[MAXN]; vector<int> pro[MAXN]; bool vis[MAXN]; int add_edge(int u,int v,int w) { etop++; e[etop].from=u; e[etop].to=v; e[etop].wgt=w; e[etop].pre=h[u]; h[u]=etop; return 0; } int main() { scanf("%d%d",&n,&m); etop=0; for(int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); if(u!=v) add_edge(u,v,w); } for(int i=1;i<=n;i++) { scanf("%d",&cnt[i]); for(int j=1;j<=cnt[i];j++) { int pr;scanf("%d",&pr); pro[pr].push_back(i); } } for(int i=0;i<=n;i++) dist[i]=INF,d[i]=0; int s;dist[s=1]=0; memset(vis,false,sizeof(vis)); for(int i=1;i<=n;i++) { int mink=0; for(int j=1;j<=n;j++) if(!vis[j]&&!cnt[j]&&max(dist[j],d[j])<max(dist[mink],d[mink])) mink=j; //if(mink==0) return 0; vis[mink]=true; for(int j=h[mink];j;j=e[j].pre) if(!vis[e[j].to]&&dist[e[j].to]>max(dist[mink],d[mink])+e[j].wgt) dist[e[j].to]=max(dist[mink],d[mink])+e[j].wgt; for(int j=pro[mink].size()-1;j>=0;j--) { cnt[pro[mink][j]]--; if(d[pro[mink][j]]<max(dist[mink],d[mink])) d[pro[mink][j]]=max(dist[mink],d[mink]); } } printf("%lld\n",max(dist ,d )); return 0; }
相关文章推荐
- 【BZOJ】1922 [Sdoi2010]大陆争霸 带限制最短路
- BZOJ1922 洛谷P2446 [SDOI2010]大陆争霸
- 【Dijkstra+贪心】BZOJ1922(Sdoi2010)[大陆争霸]题解
- BZOJ 1922 [Sdoi2010]大陆争霸 - Dijkstra
- BZOJ1922: [Sdoi2010]大陆争霸
- BZOJ[1922][Sdoi2010]大陆争霸 Dijkstra堆优化
- 【bzoj1922】[Sdoi2010]大陆争霸 最短路变形
- BZOJ1922 [SDOI2010] 大陆争霸
- 【SDOI2010】【BZOJ1922】大陆争霸
- 【bzoj1922】[Sdoi2010]大陆争霸
- BZOJ1922 [Sdoi2010]大陆争霸
- [bzoj1922][Sdoi2010]大陆争霸 dijkstra
- [Bzoj 1922] [SDOI2010] 大陆争霸
- bzoj 1922: [Sdoi2010]大陆争霸
- bzoj1922: [Sdoi2010]大陆争霸 分层图最短路
- Bzoj1922: [Sdoi2010]大陆争霸
- 【BZOJ 1922】【SDOI 2010】大陆争霸【Dijkstra】
- bzoj 1922: [Sdoi2010]大陆争霸 带限制最短路
- bzoj 1922: [Sdoi2010]大陆争霸
- bzoj 1922 [Sdoi2010]大陆争霸(最短路变形)