1. 程式人生 > >[Gym-101986F] [Problem F] 2017-2018 ACM-ICPC, Asia Tsukuba Regional Contest

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

先把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;
}