zoukankan      html  css  js  c++  java
  • Gym

    这是一个非常nice的题:
    1.map去重边,n的话有1e5,

    1 const long long base[]={20200422,1000000007,9997,7};
    2 mp[E[i].l*base[1]+E[i].r*base[2]+E[i].v*base[3]]++;


    这样来判断这条边的个数

    2.结构体封装
    好处:同样的函数不用再写好多个了,整体美观大方简洁
    坏处:如果不用多次调用其实没有必要封装

    3.边有编号的问题

    1 struct edge{
    2 long long l,r,v;
    3 }E[N];

    直接这样存第i个边的信息

    依然跑前向星,不过有所改变

     1 For(i,1,m){
     2         in(E[i].l);in(E[i].r);in(E[i].v);
     3         G1.push(E[i].l,E[i].r,E[i].v,i);
     4         G2.push(E[i].r,E[i].l,E[i].v,i);
     5         mp[E[i].l*base[1]+E[i].r*base[2]+E[i].v*base[3]]++;
     6     }
     7 
     8 void push(long long x,long long y,long long v,long long id){
     9         node *p;
    10         p=new node();
    11         p->n=y;
    12         p->v=v;
    13         p->id=id;
    14         if(e[x]==0)
    15                 e[x]=p;
    16         else{
    17                 p->next=e[x]->next;
    18                 e[x]->next=p;
    19         }
    20 }

    这样就知道了这条边的编号。

    4.这个题目的大意是把图中某一条边反转之后会导致最短路变小变大还是不变,这个题的想法本身就很妙
    设起点为s,终点为t,先求出来s到所有点的最短路,再把边反向求t到所有点的最短路,即G1.spfa(1);G2.spfa(2);

    再把组成图中最短路的所有的边全都拿出来再建一个新图

    1     For(i,1,m){
    2         if(G1.d[E[i].l]+G2.d[E[i].r]+E[i].v==G1.d[2]){
    3             G3.push(E[i].l,E[i].r,E[i].v,i);
    4             G3.push(E[i].r,E[i].l,E[i].v,i);
    5         }
    6     }

    新图上的桥是所有最短路的必经边,在这个新图上缩点,剩下的边都是桥,但是可以在跑tarjan的时候直接判了

     1     void tarjan(long long x,long long fa){
     2         dfn[x]=low[x]=++cnt;
     3         vis[x]=1;
     4         for(node *i=e[x];i;i=i->next){
     5             if(i->n==fa) continue;
     6             if(!dfn[i->n]){
     7                 tarjan(i->n,x);
     8                 low[x]=min(low[x],low[i->n]);
     9                 if(low[i->n]>dfn[x]) bi[i->id]=1;//就是这里
    10             }
    11             else
    12                 if(vis[i->n])
    13                     low[x]=min(low[x],dfn[i->n]);
    14         }
    15     }

    为什么这样可以呢?因为i->n绕了一圈也没能翻上去,所以第i->id条边本身就是桥

    最后是答案的判断:

    1     For(i,1,m){
    2         if(G1.d[E[i].r]+G2.d[E[i].l]+E[i].v<G1.d[2]) puts("HAPPY");
    3         else if(bi[i]&&mp[E[i].l*base[1]+E[i].r*base[2]+E[i].v*base[3]]==1) puts("SAD");
    4         else puts("SOSO");
    5     }

    本来是 s------>u------->v------>t

    反转后 s------>v------->u------>t
    看看新的路是不是比原来的路短,短就HAPPY
    否则如果是反转了所有最短路必经路,那么那条路就走不通了,要么不可到达,要么只能走其他不太优的路最终导致最短路变长,也就是SAD了
    其他的都是SOSO,因为反转了非必经路,走其他最短路就好了,不影响。

    5.spfa的初始化问题

    For(i,0,n) d[i]=inf;


    这个inf要足够大,我设的2147483647居然小了qwq,卡了好久,还有就是如果对拍的时候跑了很久都没挂,很可能程序是对的但是到大数据的时候出了问题

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <queue>
      4 #include <algorithm>
      5 #include <map>
      6 #include <cstring>
      7 #define inf 23333333333333
      8 #define N 1000010
      9 #define p(a) putchar(a)
     10 #define For(i,a,b) for(long long i=a;i<=b;++i)
     11 
     12 using namespace std;
     13 const long long base[]={20200422,1000000007,9997,7};
     14 long long n,m;
     15 bool bi[N];
     16 map<long long,long long>mp;
     17 void in(long long &x){
     18     long long y=1;char c=getchar();x=0;
     19     while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
     20     while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+c-'0';c=getchar();}
     21     x*=y;
     22 }
     23 void o(long long x){
     24     if(x<0){p('-');x=-x;}
     25     if(x>9)o(x/10);
     26     p(x%10+'0');
     27 }
     28 
     29 struct edge{
     30     long long l,r,v;
     31 }E[N];
     32 
     33 struct Graph{
     34     long long cnt;
     35     long long d[N],low[N],dfn[N];
     36     bool vis[N];
     37     deque<long long>q;
     38     struct node{
     39         long long n;
     40         long long v;
     41         long long id;
     42         node *next;
     43     }*e[N];
     44 
     45     void push(long long x,long long y,long long v,long long id){
     46         node *p;
     47         p=new node();
     48         p->n=y;
     49         p->v=v;
     50         p->id=id;
     51         if(e[x]==0)
     52             e[x]=p;
     53         else{
     54             p->next=e[x]->next;
     55             e[x]->next=p;
     56         }
     57     }
     58 
     59     void spfa(long long s){
     60         For(i,0,n) d[i]=inf;
     61         d[s]=0;
     62         q.push_front(s);
     63         while(!q.empty()){
     64             long long x=q.front();q.pop_front();
     65             vis[x]=1;
     66             for(node *i=e[x];i;i=i->next){
     67                 if(d[i->n]>d[x]+i->v){
     68                     d[i->n]=d[x]+i->v;
     69                     if(!vis[i->n]){
     70                         if(!q.empty()&&d[i->n]<d[q.front()]) q.push_front(i->n);
     71                         else q.push_back(i->n);
     72                         vis[i->n]=1;
     73                     }
     74                 }
     75             }
     76             vis[x]=0;            
     77         }
     78     }
     79 
     80     void tarjan(long long x,long long fa){
     81         dfn[x]=low[x]=++cnt;
     82         vis[x]=1;
     83         for(node *i=e[x];i;i=i->next){
     84             if(i->n==fa) continue;
     85             if(!dfn[i->n]){
     86                 tarjan(i->n,x);
     87                 low[x]=min(low[x],low[i->n]);
     88                 if(low[i->n]>dfn[x]) bi[i->id]=1;
     89             }
     90             else
     91                 if(vis[i->n])
     92                     low[x]=min(low[x],dfn[i->n]);
     93         }
     94     }
     95 }G1,G2,G3;
     96 
     97 signed main(){
     98     in(n);in(m);
     99     For(i,1,m){
    100         in(E[i].l);in(E[i].r);in(E[i].v);
    101         G1.push(E[i].l,E[i].r,E[i].v,i);
    102         G2.push(E[i].r,E[i].l,E[i].v,i);
    103         mp[E[i].l*base[1]+E[i].r*base[2]+E[i].v*base[3]]++;
    104     }
    105     G1.spfa(1);G2.spfa(2);
    106     For(i,1,m){
    107         if(G1.d[E[i].l]+G2.d[E[i].r]+E[i].v==G1.d[2]){
    108             G3.push(E[i].l,E[i].r,E[i].v,i);
    109             G3.push(E[i].r,E[i].l,E[i].v,i);
    110         }
    111     }
    112     G3.tarjan(1,1);
    113     For(i,1,m){
    114         if(G1.d[E[i].r]+G2.d[E[i].l]+E[i].v<G1.d[2]) puts("HAPPY");
    115         else if(bi[i]&&mp[E[i].l*base[1]+E[i].r*base[2]+E[i].v*base[3]]==1) puts("SAD");
    116         else puts("SOSO");
    117     }
    118     return 0;
    119 }
  • 相关阅读:
    Android在代码中获取应用签名
    Android之密码的显示与隐藏
    如何把本地项目上传到Github
    Android之移动热修复
    Android之apk优化
    Android之内存泄漏
    Java类加载顺序
    mysql系列-⼀条SQL查询语句是如何执⾏的?
    java操作redis(jedis)常用方法示例
    mybatis拦截器实现通用权限字段添加
  • 原文地址:https://www.cnblogs.com/war1111/p/12771389.html
Copyright © 2011-2022 走看看