[Gym-101986F] [Problem F] 2017-2018 ACM-ICPC, Asia Tsukuba Regional Contest

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/84489935