[SDOI2010]大陆争霸(最短路)
Solution
题目保证一定有解,即若从一个城市的每个结节发生器向这个城市连一条有向边,设构成的图为G1,则G1上没有环
可以看出拓扑的思想
设原图为G2
我们需要在G2上跑一种最短路,使若从G1上有一条路径从 x 到 y ,则不能用 y 更新 x 的值
可以结合拓扑和 Dijkstra
Code
#include <cstdio> #include <cstdlib> #include <queue> #include <cstring> #include <vector> #include <algorithm> #define ll long long using namespace std; const int N=3e3+10,M=14e4+10; int head[N],ver[M],nxt[M],tot; int u,v,n,m,ru[N]; ll edge[M],w,real[N],dis[N]; vector <int> son[N]; bool vis[N]; struct node { int u; ll w; bool operator <(const node &o)const { return w>o.w; } }; priority_queue <node> q; void dij() { memset(dis,0x7f,sizeof(dis)); dis[1]=real[1]=0; q.push((node){1,0}); while(!q.empty()) { int u=q.top().u; q.pop(); if(vis[u]) continue; vis[u]=true; ll now=max(dis[u],real[u]); for(int i=head[u],v;i;i=nxt[i]) if(dis[v=ver[i]]>now+edge[i]) { dis[v]=now+edge[i]; if(ru[v]==0) q.push((node){v,max(dis[v],real[v])}); } int size=son[u].size(); for(int i=0;i<size;i++) { int v=son[u][i]; real[v]=max(real[v],now); if(--ru[v]==0) q.push((node){v,max(dis[v],real[v])}); } } } void add(int u,int v,int w) { ver[++tot]=v,nxt[tot]=head[u],edge[tot]=w,head[u]=tot; } int main() { scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { scanf("%d%d%lld",&u,&v,&w); add(u,v,w); } for(int i=1;i<=n;i++) { scanf("%d",&ru[i]); for(int j=0;j<ru[i];j++) { scanf("%d",&u); son[u].push_back(i); } } dij(); printf("%lld\n",max(real[n],dis[n])); return 0; }

浙公网安备 33010602011771号