版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liufengwei1/article/details/84489935
先把1到2的最短路上的边全部标记上,标记一条边是否属于最短路,就是正着跑一遍最短路得到dis1,倒着跑一遍得到dis2,如果对于一条边u,v,c,dis1[u]+c+dis2[v]=dis1[2]那么就是最短路上的边了。
对于最短路上的边,翻转他,如果他是桥,那么最短路一定会变长,如果不是,说明还有不经过这条边的最短路,那么最短路是不变的。
对于不是最短路上的边,如果dis1[v]+c+dis2[u]<dis1[2]那么最短路就变小了,如果>=,那么说明经过这条反向边的最短路并没有比原来真正的最短路更短,那么最短路就是不变的。
求桥的方法,网上百度了一个有向图求桥,WA了半天,后来看别人有向图求桥都是先变成无向图,然后tarjan求桥。
求桥还可以利用桥的性质求,从1拓扑排序得到u点的路径数,num1[u],从2倒着拓扑排序得到到v点的路径数num2[v],如果num1[u]*num2[v]=num1[2]也就是从1到2的所有路径总数,那么u-v这条边也是最短路中的桥。
#include<bits/stdc++.h>
#define maxl 100010
using namespace std;
int n,m,cnt1,cnt2,cnt3,ind,top,ff;
int ehead1[maxl],ehead2[maxl],ehead3[maxl];
int dfn[maxl],low[maxl],s[maxl],f[maxl];
long long dis1[maxl],dis2[maxl];
struct edge
{
int x,y,l;
}edg[maxl];
struct ed
{
int to,nxt,l,id;
}e1[maxl<<1],e2[maxl<<1],e3[maxl<<1];
typedef pair <long long,int> p;
priority_queue<p,vector<p>,greater<p> > q;
bool in[maxl],edin[maxl],cut[maxl];
typedef pair <int,int> pp;
typedef pair <pp,int> ppp;
map <ppp,int> mp;
inline void add1(int u,int v,int l,int id)
{
++cnt1;e1[cnt1].to=v;e1[cnt1].nxt=ehead1[u];
e1[cnt1].l=l;e1[cnt1].id=id;ehead1[u]=cnt1;
}
inline void add2(int u,int v,int l,int id)
{
++cnt2;e2[cnt2].to=v;e2[cnt2].nxt=ehead2[u];
e2[cnt2].l=l;e2[cnt2].id=id;ehead2[u]=cnt2;
}
inline void add3(int u,int v,int l,int id)
{
++cnt3;e3[cnt3].to=v;e3[cnt3].nxt=ehead3[u];
e3[cnt3].l=l;e3[cnt3].id=id;ehead3[u]=cnt3;
}
inline void prework()
{
scanf("%d%d",&n,&m);
memset(ehead1,0,sizeof(int)*(n+1));
memset(ehead2,0,sizeof(int)*(n+1));
memset(ehead3,0,sizeof(int)*(n+1));
int x,y,l;
cnt1=0;cnt2=0;mp.clear();
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&l);
edg[i].x=x;edg[i].y=y;edg[i].l=l;
edin[i]=false;cut[i]=false;
add1(x,y,l,i);add2(y,x,l,i);
mp[make_pair(make_pair(x,y),l)]+=1;
}
}
inline void tarjan(int u,int fa)
{
int v;
bool flag=0;
dfn[u]=low[u]=++ind;s[++top]=u;in[u]=true;
for(int i=ehead3[u];i;i=e3[i].nxt)
{
v=e3[i].to;
if(v==fa&& !flag){
flag=1;
continue;
}
if(!dfn[v])
{
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u])
cut[e3[i].id]=true;
}
else
if(in[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
ff++;
do
{
v=s[top];s[top--]=0;
f[v]=ff;
in[v]=false;
}while(v!=u);
}
}
inline void mainwork()
{
while(!q.empty())
q.pop();
int u,v;p d;
for(int i=1;i<=n;i++)
dis1[i]=dis2[i]=1ll<<60;
memset(in,false,sizeof(bool)*(n+1));
dis1[1]=0;q.push(make_pair(0ll,1));
while(!q.empty())
{
do
{
d=q.top();q.pop();
u=d.second;
}while((d.first>dis1[u] || in[u]) && !q.empty());
in[u]=true;
for(int i=ehead1[u];i;i=e1[i].nxt)
{
v=e1[i].to;
if(dis1[v]>dis1[u]+e1[i].l)
{
dis1[v]=dis1[u]+e1[i].l;
q.push(make_pair(dis1[v],v));
}
}
}
while(!q.empty())
q.pop();
memset(in,false,sizeof(bool)*(n+1));
dis2[2]=0;q.push(make_pair(0ll,2));
while(!q.empty())
{
do
{
d=q.top();q.pop();
u=d.second;
}while((d.first>dis2[u] || in[u]) && !q.empty());
in[u]=true;
for(int i=ehead2[u];i;i=e2[i].nxt)
{
v=e2[i].to;
if(dis2[v]>dis2[u]+e2[i].l)
{
dis2[v]=dis2[u]+e2[i].l;
q.push(make_pair(dis2[v],v));
}
}
}
cnt3=0;
for(int i=1;i<=m;i++)
{
u=edg[i].x;v=edg[i].y;
if(dis1[u]+dis2[v]+edg[i].l==dis1[2])
{
edin[i]=true;
add3(u,v,edg[i].l,i);
add3(v,u,edg[i].l,i);
}
}
ind=0;top=0;ff=0;
memset(dfn,0,sizeof(int)*(n+1));
memset(low,0,sizeof(int)*(n+1));
memset(in,false,sizeof(bool)*(n+1));
tarjan(1,0);
}
inline void print()
{
int x,y;
for(int i=1;i<=m;i++)
{
if(edin[i])
{
if(cut[i] && mp[make_pair(make_pair(edg[i].x,edg[i].y),edg[i].l)]==1)
puts("SAD");
else
puts("SOSO");
}
else
{
x=edg[i].x;y=edg[i].y;
if(dis1[y]+edg[i].l+dis2[x]<dis1[2])
puts("HAPPY");
else
puts("SOSO");
}
}
}
int main()
{
prework();
mainwork();
print();
return 0;
}