一遇到图论就一脸懵逼,二脸惶恐,三脸放弃。。。
Dijkstra都不会写了,还是退役好了
大概就是就是类似于拓扑排序那样,对于有限制的点,其父节点遍历完成后,该节点入度–,等到入度为0即可扔进队列。需要维护两个东西,一个是实际路程,另一个是其父节点的限制,二者取个max即可。
图省事用pair一定要设为小顶堆啊啊啊,调了一个小时。。。
为什么会这么菜。。。
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn=3005;
const int maxm=70005;
typedef pair<int,int> node;
struct edge
{
int to,val,next;
}e[maxm];
int n,m,cnt;
int head[maxn],dist[maxn],lim[maxn],num[maxn];
bool vst[maxn];
vector<int>ve[maxn];
int insert(int a,int b,int c)
{
e[++cnt].to=b;e[cnt].val=c;e[cnt].next=head[a];head[a]=cnt;
}
int read()
{
int x=0;char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x;
}
void Dijkstra()
{
priority_queue<node,vector<node>,greater<node> >q;//!!!!!!!!!!!
q.push((node){0,1});
memset(dist,0x3f,sizeof dist);
dist[1]=0;
while(!q.empty())
{
node now=q.top();
q.pop();
int u=now.second;
if(vst[u])continue;
vst[u]=true;
dist[u]=max(dist[u],lim[u]);
int size=ve[u].size();
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(dist[u]+e[i].val<dist[v])
{
dist[v]=dist[u]+e[i].val;
if(!num[v])q.push((node){max(dist[v],lim[v]),v});
}
}
for(int i=0;i<size;i++)
{
num[ve[u][i]]--,lim[ve[u][i]]=max(lim[ve[u][i]],dist[u]);
if(!num[ve[u][i]])q.push((node){max(lim[ve[u][i]],dist[ve[u][i]]),ve[u][i]});
}
}
}
int main()
{
n=read(),m=read();
for(int i=1;i<=m;i++)
{
int u,v,val;
scanf("%d%d%d",&u,&v,&val);
if(u!=v)insert(u,v,val);
}
for(int i=1,a;i<=n;i++)
{
a=num[i]=read();
while(a--)
ve[read()].push_back(i);
}
Dijkstra();
printf("%d",dist[n]);
return 0;
}