习题:President and Roads(最短路)
题目
思路
经过边的必然性很容易将其和桥联系起来
考虑如果可能经过一条边,那么这条边一定在最短路上面
可以预处理出这些最短路所构成的图
如果经过某一条边,那么这条边必然在图上是一个桥,因为题目中可能出现重边,所以在tarjan的时候要改一下continue的条件
如果要经过某一条边,那么我们只需要将经过这条边的最短路比原来的最短路小即可
用前向星会好写很多,笔者当时脑子一抽就写了vector
代码
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<queue>
#include<stack>
#include<map>
using namespace std;
namespace IO
{
void read(int &x)
{
x=0;
int f=1;
char c=getchar();
while('0'>c||c>'9')
{
if(f=='-')
f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
void read(long long &x)
{
x=0;
int f=1;
char c=getchar();
while('0'>c||c>'9')
{
if(f=='-')
f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
void write(int x)
{
if(x<10)
putchar(x+'0');
else
{
write(x/10);
putchar(x%10+'0');
}
}
void write(long long x)
{
if(x<10)
putchar(x+'0');
else
{
write(x/10);
putchar(x%10+'0');
}
}
}
using namespace IO;
struct graph
{
struct node
{
int e;
long long w;
friend bool operator < (const node &a,const node &b)
{
return a.w>b.w;
}
};
int n,id;
int dfn[100005],low[100005],bel[100005],cnt,scc;
bool ins[100005];
long long dis[100005];
stack<int> s;
priority_queue<node> q;
vector<node> g[100005];
vector<int> dag[100005];
map<int,int> f[100005];
void add_edge(int u,int v,long long w)
{
g[u].push_back((node){v,w});
}
void dij(int u)
{
memset(dis,0x3f,sizeof(dis));
q.push((node){u,0});
while(!q.empty())
{
node t=q.top();
q.pop();
if(t.w>=dis[t.e])
continue;
dis[t.e]=t.w;
for(int i=0;i<g[t.e].size();i++)
{
int v=g[t.e][i].e;
if(dis[v]>t.w+g[t.e][i].w)
q.push((node){v,t.w+g[t.e][i].w});
}
}
}
void build()
{
for(int i=1;i<=n;i++)
for(int j=0;j<g[i].size();j++)
if(dis[i]+g[i][j].w==dis[g[i][j].e])
{
dag[i].push_back(g[i][j].e);
dag[g[i][j].e].push_back(i);
f[i][dag[i].size()-1]=++id;
f[g[i][j].e][dag[g[i][j].e].size()-1]=id;
}
}
void tarjan(int u,int fa)
{
s.push(u);
ins[u]=1;
dfn[u]=low[u]=++cnt;
for(int i=0;i<dag[u].size();i++)
{
int v=dag[u][i];
if(f[u][i]==fa)
continue;
if(dfn[v]==0)
{
tarjan(v,f[u][i]);
low[u]=min(low[u],low[v]);
}
else if(ins[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
int v;
scc++;
do
{
v=s.top();
s.pop();
ins[v]=0;
bel[v]=scc;
}while(v!=u);
}
}
void debug()
{
for(int i=1;i<=n;i++)
for(int j=0;j<g[i].size();j++)
if(dis[i]+g[i][j].w==dis[g[i][j].e])
cout<<i<<' '<<g[i][j].e<<'\n';
for(int i=1;i<=n;i++)
cout<<bel[i]<<' ';
cout<<'\n';
}
}g1,g2;
struct edge
{
int u,v;
long long w;
}a[100005];
int n,m,s,t;
int main()
{
read(n);read(m);read(s);read(t);
g1.n=g2.n=n;
for(int i=1,u,v;i<=m;i++)
{
long long w;
read(u);read(v);read(w);
a[i].u=u;a[i].v=v;a[i].w=w;
g1.add_edge(u,v,w);
g2.add_edge(v,u,w);
}
g1.dij(s);g2.dij(t);
for(int i=1;i<=m;i++)
if(g1.dis[a[i].u]+a[i].w+g2.dis[a[i].v]==g1.dis[t])
{
g1.dag[a[i].u].push_back(a[i].v);
g1.dag[a[i].v].push_back(a[i].u);
g1.f[a[i].u][g1.dag[a[i].u].size()-1]=++g1.id;
g1.f[a[i].v][g1.dag[a[i].v].size()-1]=g1.id;
}
for(int i=1;i<=n;i++)
if(g1.dfn[i]==0)
g1.tarjan(i,0);
for(int i=1;i<=m;i++)
{
if(g1.bel[a[i].u]!=g1.bel[a[i].v]&&g1.dis[a[i].u]+a[i].w+g2.dis[a[i].v]==g1.dis[t])
puts("YES");
else if(g1.dis[t]-1-g1.dis[a[i].u]-g2.dis[a[i].v]<=0)
puts("NO");
else
{
printf("CAN ");
write(a[i].w-(g1.dis[t]-1-g1.dis[a[i].u]-g2.dis[a[i].v]));
putchar('\n');
}
}
return 0;
}

浙公网安备 33010602011771号